Skip to content

Commit 36fd2dc

Browse files
committed
osv vendor vulnerability scanning
1 parent 2da7d27 commit 36fd2dc

File tree

11 files changed

+98
-24
lines changed

11 files changed

+98
-24
lines changed

.github/scripts/otp-compliance.es

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,18 @@ cli() ->
216216
> .github/scripts/otp-compliance.es sbom vendor --sbom-file otp.spdx.json
217217
""",
218218
arguments => [ sbom_option()],
219-
handler => fun sbom_vendor/1}
219+
handler => fun sbom_vendor/1},
220+
221+
"osv-scan" =>
222+
#{ help =>
223+
"""
224+
Performs vulnerability scanning on vendor libraries
225+
226+
Example:
227+
228+
> .github/scripts/otp-compliance.es sbom osv-scan
229+
""",
230+
handler => fun osv_scan/1}
220231
}},
221232
"explore" =>
222233
#{ help => """
@@ -1205,6 +1216,68 @@ generate_vendor_purl(Package) ->
12051216
[create_externalRef_purl(Description, <<Purl/binary, "@", Vsn/binary>>)]
12061217
end.
12071218

1219+
osv_scan(_) ->
1220+
application:ensure_all_started([ssl, inets]),
1221+
URI = "https://api.osv.dev/v1/querybatch",
1222+
Format = "application/x-www-form-urlencoded",
1223+
1224+
VendorSrcFiles = find_vendor_src_files("."),
1225+
Packages = generate_vendor_info_package(VendorSrcFiles),
1226+
1227+
OSVQuery = generate_osv_query(Packages),
1228+
io:format("[OSV] Information sent~n~s~n", [json:format(OSVQuery)]),
1229+
OSV = json:encode(OSVQuery),
1230+
1231+
Content = {URI, [], Format, OSV},
1232+
Result = httpc:request(post, Content, [], []),
1233+
case Result of
1234+
{ok,{{_, 200,_}, _Headers, Body}} ->
1235+
#{~"results" := OSVResults} = json:decode(erlang:list_to_binary(Body)),
1236+
Vulnerabilities = lists:filter(fun (#{~"vulns" := _Ids}) -> true; (_) -> false end, OSVResults),
1237+
case Vulnerabilities of
1238+
[] ->
1239+
io:format("[OSV] No vulnerabilities found.~n");
1240+
_ ->
1241+
FormatVulns = format_vulnerabilities(OSVQuery, OSVResults),
1242+
fail("[OSV] There are existing vulnerabilities:~n~s", [FormatVulns])
1243+
end;
1244+
{error, Error} ->
1245+
fail("[OSV] POST request to ~p errors: ~p", [URI, Error])
1246+
end.
1247+
1248+
format_vulnerabilities(OSVQuery, OSVResults) ->
1249+
NameVulnerabilities = lists:zip(osv_names(OSVQuery), OSVResults),
1250+
ExistingVulnerabilities = lists:filtermap(fun ({Name, #{~"vulns" := Ids}}) ->
1251+
{true, {Name, [Id || #{~"id" := Id} <- Ids]}};
1252+
(_) ->
1253+
false
1254+
end, NameVulnerabilities),
1255+
lists:map(fun ({N, Ids}) ->
1256+
io_lib:format("- ~s: ~s~n", [N, lists:join(",", Ids)])
1257+
end, ExistingVulnerabilities).
1258+
1259+
osv_names(#{~"queries" := Packages}) ->
1260+
lists:map(fun osv_names/1, Packages);
1261+
osv_names(#{~"package" := #{~"name" := Name }}) ->
1262+
Name.
1263+
1264+
generate_osv_query(Packages) ->
1265+
#{~"queries" => lists:foldl(fun generate_osv_query/2, [], Packages)}.
1266+
generate_osv_query(#{~"versionInfo" := Vsn, ~"ecosystem" := Ecosystem, ~"name" := Name}, Acc) ->
1267+
Package = #{~"package" => #{~"name" => Name, ~"ecosystem" => Ecosystem}, ~"version" => Vsn},
1268+
[Package | Acc];
1269+
generate_osv_query(#{~"sha" := SHA, ~"downloadLocation" := Location}, Acc) ->
1270+
case string:prefix(Location, ~"https://") of
1271+
nomatch ->
1272+
Acc;
1273+
URI ->
1274+
Package = #{~"package" => #{~"name" => URI}, ~"commit" => SHA},
1275+
[Package | Acc]
1276+
end;
1277+
generate_osv_query(_, Acc) ->
1278+
Acc.
1279+
1280+
12081281
cleanup_path(<<"./", Path/binary>>) when is_binary(Path) -> Path;
12091282
cleanup_path(Path) when is_binary(Path) -> Path.
12101283

.github/workflows/main.yaml

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -864,11 +864,6 @@ jobs:
864864
with:
865865
BASE_BRANCH: ${{ env.BASE_BRANCH }}
866866

867-
- name: Download SBoM
868-
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # ratchet:actions/[email protected]
869-
with:
870-
name: ort-results-otp-${{ env.OTP_SBOM_VERSION }}
871-
872867
- name: Generate Vendor SBOM
873868
run: |
874869
docker run -v $PWD/:/github -v $HOME:$HOME otp \
@@ -881,17 +876,10 @@ jobs:
881876
uses: advanced-security/spdx-dependency-submission-action@5530bab9ee4bbe66420ce8280624036c77f89746 # ratchet:advanced-security/[email protected]
882877

883878
# check that PRs do not introduce vulnerabilities in vendor dependencies
884-
- name: 'Dependency Review'
885-
uses: actions/dependency-review-action@ce3cf9537a52e8119d91fd484ab5b8a807627bf8 #ratchet:actions/dependency-review-action@v4
886-
with:
887-
vulnerability-check: true
888-
fail-on-severity: low # fail if there are dependency issues with low severity impact.
889-
license-check: false # skip, we have our license process
890-
comment-summary-in-pr: never # displays summary as a comment. we could test with 'on-failure'
891-
warn-only: false # do not warn only (fail instead)
892-
show-openssf-scorecard: true # applied to dependencies changed in this PR, not to OTP
893-
warn-on-openssf-scorecard-level: 3 # scorecard level in which a dependency is considered problematic
894-
879+
- name: 'Vendor Vulnerability Scanning'
880+
run: |
881+
docker run -v $PWD/:/github -v $HOME:$HOME otp \
882+
"/github/.github/scripts/otp-compliance.es sbom osv-scan"
895883
896884
## If this is an "OTP-*" tag that has been pushed we do some release work
897885
release:

HOWTO/SBOM.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ This file may be a list of JSON objects. For simplicity, we document the fields
183183
"licenseDeclared": "Zlib",
184184
"name": "asmjit",
185185
"versionInfo": "a465fe71ab3d0e224b2b4bd0fac69ae68ab9239d",
186+
"sha": "a465fe71ab3d0e224b2b4bd0fac69ae68ab9239d",
186187
"path": "./erts/emulator/asmjit",
187188
"supplier": "Person: Petr Kobalicek",
188189
"purl": "pkg:github/asmjit/asmjit"
@@ -204,6 +205,9 @@ Fields summary:
204205
- `licenseDeclared`: license as declared by the vendor, following a [SPDX license identifier](https://spdx.org/licenses/).
205206
- `name`: name of the library.
206207
- `versionInfo`: version of the library/project/3pp. In case of no version number being available, write the commit sha.
208+
- `sha`: sha commit for `versionInfo`, they need to be updated together!
209+
- `ecosystem`: List of valid ecosystems in [OSV Ecosystems](https://ossf.github.io/osv-schema/#defined-ecosystems)
210+
where this value is omitted for C/C++ code (e.g., `asmjit`, `pcre2`, `zlib`, `zstd`, etc), and used in `vendor.json` for `jquery`.
207211
- `path`: path to the vendor library inside Erlang/OTP. This can point to a folder or a list of files.
208212
- Folder: any file inside the folder is considered part of the vendor library (e.g., asmjit [vendor.info](../erts/emulator/asmjit/vendor.info)).
209213
- List of files: only the files listed here are part of a vendor library (e.g., erts-config [vendor.info](../erts/autoconf/vendor.info)).

erts/emulator/asmjit/vendor.info

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"licenseDeclared": "Zlib",
1616
"name": "asmjit",
1717
"versionInfo": "a465fe71ab3d0e224b2b4bd0fac69ae68ab9239d",
18+
"sha": "a465fe71ab3d0e224b2b4bd0fac69ae68ab9239d",
1819
"path": "./erts/emulator/asmjit",
1920
"supplier": "Person: Petr Kobalicek",
2021
"purl": "pkg:github/asmjit/asmjit"

erts/emulator/openssl/vendor.info

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"licenseDeclared": "Apache-2.0",
1616
"name": "openssl",
1717
"versionInfo": "3.5",
18+
"sha": "636dfadc70ce26f2473870570bfd9ec352806b1d",
1819
"path": "./erts/emulator/openssl",
1920
"supplier": "Organization: OpenSSL Mission",
2021
"purl": "pkg:generic/openssl"

erts/emulator/pcre/vendor.info

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
"ID": "erts-pcre",
1111
"description": "PCRE2 library",
1212
"copyrightText": "NOASSERTION",
13-
"downloadLocation": "git+https://github.com/PCRE2Project/pcre2.git",
13+
"downloadLocation": "https://github.com/PCRE2Project/pcre2",
1414
"homepage": "https://pcre2project.github.io/pcre2/",
1515
"licenseDeclared": "BSD-3-Clause",
1616
"name": "pcre2",
17-
"versionInfo": "10.44",
17+
"versionInfo": "10.45",
1818
"path": "./erts/emulator/pcre",
19+
"sha": "2dce7761b1831fd3f82a9c2bd5476259d945da4d",
1920
"supplier": "Person: Philip Hazel",
2021
"purl": "pkg:generic/pcre2"
2122
}

erts/emulator/zlib/vendor.info

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
"ID": "erts-zlib",
1111
"description": "interface of the 'zlib' general purpose compression library",
1212
"copyrightText": "Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler",
13-
"downloadLocation": "https://zlib.net/",
13+
"downloadLocation": "https://github.com/madler/zlib",
1414
"homepage": "https://zlib.net/",
1515
"licenseDeclared": "Zlib",
1616
"name": "zlib",
1717
"versionInfo": "1.3.1",
18+
"sha": "51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf",
1819
"path": "./erts/emulator/zlib",
1920
"supplier": "Person: Mark Adler ([email protected])",
20-
"purl": "pkg:generic/zlib"
21+
"purl": "pkg:github/madler/zlib"
2122
}
2223
]

erts/emulator/zstd/vendor.info

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"licenseDeclared": "BSD-3-Clause OR GPL-2.0-only",
1717
"name": "zstd",
1818
"versionInfo": "v1.5.7",
19+
"sha": "f8745da6ff1ad1e7bab384bd1f9d742439278e99",
1920
"path": "./erts/emulator/zstd",
2021
"supplier": "Organization: Meta",
2122
"purl": "pkg:github/facebook/zstd",

lib/common_test/priv/vendor.info

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"downloadLocation": "https://github.com/jquery/jquery",
1414
"homepage": "https://jquery.com",
1515
"licenseDeclared": "MIT",
16+
"ecosystem": "npm",
1617
"name": "jquery",
1718
"versionInfo": "3.7.1",
1819
"path": ["./lib/common_test/priv/jquery-latest.js"],
@@ -26,7 +27,8 @@
2627
"downloadLocation": "https://github.com/Mottie/tablesorter",
2728
"homepage": "https://github.com/Mottie/tablesorter",
2829
"licenseDeclared": "BSD-3-Clause OR GPL-2.0-only",
29-
"name": "jquery-tablesorter",
30+
"ecosystem": "npm",
31+
"name": "tablesorter",
3032
"versionInfo": "2.32",
3133
"path": ["./lib/common_test/priv/jquery.tablesorter.min.js"],
3234
"supplier": "Person: Christian Bach",

lib/erl_interface/src/openssl/vendor.info

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"licenseDeclared": "Apache-2.0",
1616
"name": "openssl",
1717
"versionInfo": "3.5",
18+
"sha": "636dfadc70ce26f2473870570bfd9ec352806b1d",
1819
"path": "./lib/erl_interface/src/openssl",
1920
"supplier": "Organization: OpenSSL Mission",
2021
"purl": "pkg:generic/openssl"

lib/wx/vendor.info

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
"homepage": "https://github.com/wxWidgets/wxWidgets",
1515
"licenseDeclared": "LicenseRef-scancode-wxwindows-free-doc-3",
1616
"name": "wx",
17-
"versionInfo": "dc585039bbd426829e3433002023a93f9bedd0c2",
17+
"versionInfo": "f2918a9ac823074901ce27de939baa57788beb3d",
18+
"sha": "f2918a9ac823074901ce27de939baa57788beb3d",
1819
"path": "./lib/wx",
19-
"comments": "This only applies to the source code of Erlang files in 'src', and specifically to the documentation embedded in them",
20+
"comments": "This only applies to the source code of Erlang files in 'src', and specifically to the documentation embedded in them.",
2021
"supplier": "NOASSERTION",
2122
"purl": "pkg:github/wxwidgets/wxwidgets"
2223
}

0 commit comments

Comments
 (0)