← 返回首页
Java: CWE-378: Temp Directory Hijacking Race Condition Vulnerability by JLLeitschuh · Pull Request #4473 · github/codeql · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ba727af
Java: CWE-378: Temp Directory Hijacking Race Condition Vulnerability
JLLeitschuh Oct 14, 2020
aea0170
Better temp file deletion and file creation tracking
JLLeitschuh Oct 14, 2020
545eb2c
Fix inverted predicate logic and add additional test cases
JLLeitschuh Oct 15, 2020
253c96f
Improve TempDir hijacking detection with Guard
JLLeitschuh Jan 19, 2022
d9d5b67
Improve warning in TempDirHijackingVulnerability
JLLeitschuh Jan 19, 2022
1fc7629
Add documentation and additional test cases
JLLeitschuh Jan 20, 2022
b42ff13
Improve TempDirHijackingVulnerability message
JLLeitschuh Jan 20, 2022
20bd05b
Add predicate handling `isDirectory` case
JLLeitschuh Mar 9, 2022
442ef83
Add deleteOnExit as safe usage
JLLeitschuh Mar 10, 2022
fbecfdd
Start taint hijacking tracking with `java.io.tmpdir`
JLLeitschuh Mar 15, 2022
8a7d64d
Refactor common logic into TempFileLib
JLLeitschuh Mar 15, 2022
884db9e
Refactor more logic to TempFileLib
JLLeitschuh Mar 15, 2022
6f4ed4b
Apply suggestions from code review
JLLeitschuh Mar 16, 2022
03983f1
Refactor TempDirHijacking to show complete path
JLLeitschuh Mar 16, 2022
37b1e1d
Update to use new getSystemProperty predicate
JLLeitschuh Mar 18, 2022
ac8e1cc
Add additional test cases
JLLeitschuh Mar 18, 2022
84003c1
Fix some false positive paths with FlowState
JLLeitschuh Mar 18, 2022
4b6d1a4
Finalize and document FlowState usage
JLLeitschuh Mar 18, 2022
325d0e1
Add `NullLiteral` flow check for `File.createTempFile`
JLLeitschuh Mar 18, 2022
71f5fc5
Add additional tests and better tracking of 'unsafe use'
JLLeitschuh Mar 29, 2022
140c66e
Add additional tests cases for mkdir wrapper method checking
JLLeitschuh Mar 30, 2022
21bef99
Add release notes
JLLeitschuh Mar 30, 2022
407dd05
Rename localExprFlowPlusInitializers to localExprOrInitializerFlow
JLLeitschuh Mar 30, 2022
0f5a1e7
Expand isDeleteFileExpr to include delete method wrappers
JLLeitschuh Mar 31, 2022
e7f016e
Apply suggestions from code review
JLLeitschuh Apr 25, 2022
3a50253
Fix implicit 'this' use in TempFileLib
JLLeitschuh Apr 28, 2022
cd3662c
Cleanup after rebase on `main`
JLLeitschuh May 3, 2022
a2a7c73
Clean up function naming, documentation, and to some degree code with…
smowton May 9, 2022
b412c7f
Merge pull request #8 from smowton/feat/JLL/java/CWE-378
JLLeitschuh Jun 1, 2022
File filter

Filter by extension

Filter by extension .java  (1) .ql  (1) .qll  (1) All 3 file types selected Viewed files
Conversations
Failed to load comments. Retry
Loading
Jump to
Jump to file
Failed to load files. Retry
Loading
Diff view
Unified
Split
Hide whitespace
Apply and reload
Show whitespace
Diff view
Unified
Split
Hide whitespace
Apply and reload
  • java/ql
    • src/Security/CWE
    • test/query-tests/security/CWE-378/semmle/tests
      • Test.java
Prev Previous commit
Next Next commit
Start taint hijacking tracking with java.io.tmpdir
  • Loading branch information
JLLeitschuh committed May 3, 2022
commit fbecfdd8184f0f7892211f739f3f8648cdd8dc37
2 changes: 1 addition & 1 deletion java/ql/src/Security/CWE/CWE-200/TempDirUtils.qll
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private class FileSetRedableMethodAccess extends MethodAccess {

/**
* Hold's if temporary directory's use is protected if there is an explicit call to
* `setReadable(false, false)`, then `setRedabale(true, true)`.
* `setReadable(false, false)`, then `setReadable(true, true)`.
*/
predicate isPermissionsProtectedTempDirUse(DataFlow::Node sink) {
exists(FileSetRedableMethodAccess setReadable1, FileSetRedableMethodAccess setReadable2 |
Expand Down
31 changes: 18 additions & 13 deletions java/ql/src/Security/CWE/CWE-378/TempDirHijackingVulnerability.ql
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,26 @@ private class MethodFileDelete extends Method {
}

predicate isDeleteFileExpr(Expr expr) {
exists(MethodAccess ma |
expr = ma.getQualifier() and
ma.getMethod() instanceof MethodFileDelete
)
expr = any(MethodFileDelete m).getAReference().getQualifier()
}

private class TempDirHijackingToDeleteConfig extends DataFlow::Configuration {
private class TempDirHijackingToDeleteConfig extends TaintTracking::Configuration {
TempDirHijackingToDeleteConfig() { this = "TempDirHijackingToDeleteConfig" }

override predicate isSource(DataFlow::Node source) {
exists(MethodAccess ma |
ma.getMethod() instanceof MethodFileCreateTempFile and
source.asExpr() = ma
)
source.asExpr() =
any(MethodAccess ma |
ma.getMethod() instanceof MethodFileCreateTempFile and ma.getNumArgument() = 2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

Might be good to explain why check for = 2, that is, to match the method creating a file in the default OS temp directory.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

Done!

) or
// TODO: Replace with getSystemProperty("java.io.tmpdir")
source.asExpr() = any(MethodAccessSystemGetProperty maSgp | maSgp.hasCompileTimeConstantGetPropertyName("java.io.tmpdir"))
}

override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
node2.asExpr() =
any(MethodAccess ma |
ma.getMethod() instanceof MethodFileCreateTempFile and ma.getArgument(2) = node1.asExpr()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

Is this taint step correct in case the source is already a MethodFileCreateTempFile?
It looks like this taint step is only intended for the case where File.createTempFile is called with java.io.tmpdir as parent directory.

(Though apparently the tests cover this and pass?)

)
}

override predicate isSink(DataFlow::Node sink) { isDeleteFileExpr(sink.asExpr()) }
Expand Down Expand Up @@ -137,11 +143,10 @@ private predicate safeUse(Expr e) {

from
DataFlow::PathNode source, DataFlow::PathNode deleteCheckpoint, DataFlow2::Node deleteCheckpoint2,
DataFlow2::Node sink, MethodAccess creationCall, Expr unsafe,
TempDirHijackingToDeleteConfig toDeleteConfig, TempDirHijackingFromDeleteConfig fromDeleteConfig
DataFlow2::Node sink, MethodAccess creationCall, Expr unsafe
where
toDeleteConfig.hasFlowPath(source, deleteCheckpoint) and
fromDeleteConfig.hasFlow(deleteCheckpoint2, sink) and
any(TempDirHijackingToDeleteConfig c).hasFlowPath(source, deleteCheckpoint) and
any(TempDirHijackingFromDeleteConfig c).hasFlow(deleteCheckpoint2, sink) and
deleteCheckpoint.getNode().asExpr() = deleteCheckpoint2.asExpr() and
isUnsafeUseUnconstrainedByIfCheck(sink, unsafe) and
isNonThrowingDirectoryCreationExpression(sink.asExpr(), creationCall)
Expand Down
Show comments View file Edit file Delete file Open in desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,19 @@ static File safe9() throws IOException {
}
return temp;
}

static File vulnerable2() throws IOException {
File temp = File.createTempFile("test", "directory", new File(System.getProperty("java.io.tmpdir")));
temp.delete();
temp.mkdir();
return temp;
}

static File safe10() throws IOException {
File temp = File.createTempFile("test", "directory", new File(System.getProperty("user.dir")));
temp.delete();
temp.mkdir();
return temp;
}

}
Toggle all file notes Toggle all file annotations

Footer

© 2026 GitHub, Inc.