Skip to content

Commit 3c8c240

Browse files
Merge pull request #94 from advanced-security/jeongsoolee09/cover-multi-service-log-i
Cover multi-service log injection
2 parents 36a6254 + 66a067c commit 3c8c240

File tree

92 files changed

+11309
-6136
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+11309
-6136
lines changed

.github/workflows/code_scanning.yml

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ on:
88
branches: [ "main" ]
99
schedule:
1010
- cron: '39 12 * * 2'
11-
11+
workflow_dispatch:
12+
1213
env:
1314
LGTM_INDEX_XML_MODE: all
15+
LGTM_INDEX_FILTERS: "include:**/*.json"
1416

1517
jobs:
1618
analyze:
@@ -35,6 +37,24 @@ jobs:
3537
mv $dir .github/codeql/extensions/$dir
3638
done
3739
40+
- name: Ensure presence of cds shell command
41+
run: |
42+
if ! command -v cds &> /dev/null
43+
then
44+
npm install -g @sap/cds-dk
45+
fi
46+
47+
# Compile .cds files to .cds.json files.
48+
- name: Compile CAP CDS files
49+
run: |
50+
for cds_file in $(find . -type f \( -iname '*.cds' \) -print)
51+
do
52+
echo "I am compiling $cds_file"
53+
cds compile $cds_file \
54+
-2 json \
55+
-o "$cds_file.json"
56+
done
57+
3858
# Initializes the CodeQL tools for scanning.
3959
- name: Initialize CodeQL
4060
uses: github/codeql-action/init@v3
@@ -46,17 +66,17 @@ jobs:
4666
- name: Perform CodeQL Analysis
4767
id: analyze
4868
uses: github/codeql-action/analyze@v3
49-
69+
5070
- name: Setup Python
5171
uses: actions/setup-python@v5
5272
with:
53-
python-version: '3.10'
54-
73+
python-version: '3.10'
74+
5575
- uses: actions/cache@v4
5676
with:
5777
path: ~/.cache/pip
5878
key: ${{ runner.os }}-pip
59-
79+
6080
- name: Validate results
6181
continue-on-error: true
6282
id: validate
@@ -66,7 +86,7 @@ jobs:
6686
sarif diff ${{ steps.analyze.outputs.sarif-output }} .github/workflows/javascript.sarif.expected -o sarif-diff.json
6787
cat sarif-diff.json
6888
! grep -q "[1-9]" sarif-diff.json
69-
89+
7090
- name: Upload sarif change
7191
if: steps.validate.outcome != 'success'
7292
uses: actions/upload-artifact@v4
@@ -75,10 +95,9 @@ jobs:
7595
path: |
7696
sarif-diff.json
7797
${{ steps.analyze.outputs.sarif-output }}
78-
98+
7999
- name: Unexpected Code Scanning results
80100
if: steps.validate.outcome != 'success'
81101
run: |
82102
cat sarif-diff.json
83103
echo "::error::Unexpected Code Scanning results!" && exit 1
84-

.github/workflows/javascript.sarif.expected

Lines changed: 7897 additions & 5677 deletions
Large diffs are not rendered by default.

.github/workflows/run-codeql-unit-tests-javascript.yml

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
with:
5252
qlt-version: 'latest'
5353
add-to-path: true
54-
54+
5555
- name: Install CodeQL
5656
id: install-codeql
5757
shell: bash
@@ -61,13 +61,13 @@ jobs:
6161
echo "-----------------------------"
6262
echo "CodeQL Home: $QLT_CODEQL_HOME"
6363
echo "CodeQL Binary: $QLT_CODEQL_PATH"
64-
64+
6565
- name: Verify Versions of Tooling
6666
shell: bash
6767
run: |
6868
echo -e "Checking CodeQL Version:"
6969
$QLT_CODEQL_PATH --version
70-
70+
7171
echo -e "Checking QLT Version:"
7272
echo "QLT Home: ${{ steps.install-qlt.outputs.qlt-home }}"
7373
qlt version
@@ -77,6 +77,24 @@ jobs:
7777
run: |
7878
qlt query run install-packs
7979
80+
- name: Ensure presence of cds shell command
81+
run: |
82+
if ! command -v cds &> /dev/null
83+
then
84+
npm install -g @sap/cds-dk
85+
fi
86+
87+
# Compile .cds files to .cds.json files.
88+
- name: Compile CAP CDS files
89+
run: |
90+
for cds_file in $(find . -type f \( -iname '*.cds' \) -print)
91+
do
92+
echo "I am compiling $cds_file"
93+
cds compile $cds_file \
94+
-2 json \
95+
-o "$cds_file.json"
96+
done
97+
8098
- name: Run test suites
8199
id: run-test-suites
82100
env:
@@ -86,16 +104,17 @@ jobs:
86104
CODEQL_STDLIB_IDENT: ${{matrix.codeql_standard_library_ident}}
87105
RUNNER_TMP: ${{ runner.temp }}
88106
LGTM_INDEX_XML_MODE: all
107+
LGTM_INDEX_FILTERS: "include:**/*.json"
89108

90109
shell: bash
91110
run: >
92-
qlt test run execute-unit-tests
111+
qlt test run execute-unit-tests
93112
--codeql-args "--threads=0 --strict-test-discovery"
94-
--num-threads 2
95-
--language javascript
96-
--runner-os $RUNNER_OS
113+
--num-threads 2
114+
--language javascript
115+
--runner-os $RUNNER_OS
97116
--work-dir $RUNNER_TMP
98-
117+
99118
- name: Upload test results
100119
uses: actions/upload-artifact@v2
101120
with:
@@ -119,12 +138,12 @@ jobs:
119138
with:
120139
qlt-version: 'latest'
121140
add-to-path: true
122-
141+
123142

124143
- name: Collect test results
125144
uses: actions/download-artifact@v2
126145

127146
- name: Validate test results
128-
run: |
147+
run: |
129148
qlt test run validate-unit-tests --pretty-print --results-directory . >> $GITHUB_STEP_SUMMARY
130-
qlt test run validate-unit-tests --results-directory .
149+
qlt test run validate-unit-tests --results-directory .
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Definitions pertaining to the application as a whole.
3+
*/
4+
5+
import javascript
6+
import advanced_security.javascript.frameworks.cap.PackageJson
7+
8+
class RootDirectory extends Folder {
9+
RootDirectory() {
10+
exists(PackageJson packageJson | this = packageJson.getJsonFile().getParentContainer())
11+
}
12+
13+
/**
14+
* Gets the path of a file relative to this root directory.
15+
*/
16+
string getFilePathRelativeToRoot(File file) {
17+
result = file.getAbsolutePath().regexpReplaceAll(this.getAbsolutePath(), ".") and
18+
result.charAt(0) = "."
19+
}
20+
21+
/**
22+
* Holds if this root directory of the application contains the given file.
23+
*/
24+
predicate contains(File file) { exists(this.getFilePathRelativeToRoot(file)) }
25+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import javascript
2+
import semmle.javascript.dataflow.DataFlow
3+
import semmle.javascript.security.dataflow.LogInjectionQuery
4+
import advanced_security.javascript.frameworks.cap.RemoteFlowSources
5+
import advanced_security.javascript.frameworks.cap.CDS
6+
import advanced_security.javascript.frameworks.cap.dataflow.DataFlow
7+
8+
/**
9+
* A logger obtained by a call to `log` on a CDS facade. Each logger is associated with
10+
* its unique name.
11+
*/
12+
class CdsLogger extends MethodCallNode {
13+
string name;
14+
15+
CdsLogger() {
16+
exists(CdsFacade cds |
17+
this = cds.getMember("log").getACall() and
18+
name = this.getArgument(0).getALocalSource().asExpr().(StringLiteral).getValue()
19+
)
20+
}
21+
22+
string getName() { result = name }
23+
}
24+
25+
/**
26+
* Arguments of calls to `cds.log.{trace, debug, info, log, warn, error}`
27+
*/
28+
class CdsLogSink extends DataFlow::Node {
29+
CdsLogSink() {
30+
exists(CdsLogger log, MethodCallNode loggingMethod |
31+
this = loggingMethod.getAnArgument() and
32+
loggingMethod.getMethodName() = ["trace", "debug", "info", "log", "warn", "error"] and
33+
not this.asExpr() instanceof Literal and
34+
not this.asExpr() instanceof TemplateLiteral and
35+
loggingMethod.getReceiver().getALocalSource() = log
36+
)
37+
}
38+
}
39+
40+
class CAPLogInjectionConfiguration extends LogInjectionConfiguration {
41+
override predicate isSource(DataFlow::Node start) {
42+
super.isSource(start) or
43+
start instanceof RemoteFlowSource
44+
}
45+
46+
override predicate isSink(DataFlow::Node end) { end instanceof CdsLogSink }
47+
}

0 commit comments

Comments
 (0)