Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions .github/workflows/export-osv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Update IDs, timestamps, and export OSV

on:
pull_request:
push:
branches:
- main

jobs:
update-and-export:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup Julia
uses: julia-actions/setup-julia@v1

- name: Install Julia dependencies
run: |
julia --project=. -e 'using Pkg; Pkg.instantiate()'

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 'stable'

- name: Install osv-linter
run: |
git clone https://github.com/JuliaComputing/osv-schema.git -b juliahub/julia
cd ./osv-schema/tools/osv-linter
go build -o ../../../osv-linter ./cmd/osv
cd ../../..
rm -rf osv-schema

- name: Assign ids and timestamps
id: assign
run: |
julia --project=. scripts/assign_ids_and_dates.jl

- name: Push updated advisories to main
if: ${{ steps.assign.outputs.changes && github.event_name == 'push' && github.ref_name == 'main' }}
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add advisories
git commit -m '${{ steps.assign.outputs.title }}'
git push origin main

- name: Export OSV
id: export
run: |
julia --project=. scripts/export_osv.jl
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Validate JSON
run: |
output=$(./osv-linter record lint osv 2>&1 || true)
if [ -n "$output" ]; then
echo "$output"
exit 1
fi

- name: Publish OSV data
if: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
env:
GITHUB_BRANCH: ${{ github.ref_name }}
GITHUB_SHA: ${{ github.sha }}
run: |
DATA_DIR=$PWD/osv
BRANCH=generated/osv
REF=refs/remotes/origin/$BRANCH
export GIT_WORK_TREE=$DATA_DIR
git read-tree "$REF"
git add --all --intent-to-add
git diff --quiet && exit
git add --all
TREE=$(git write-tree)
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
COMMIT=$(git commit-tree "$TREE" -p "$REF" -m "[automated] export ($GITHUB_BRANCH)@($GITHUB_SHA)")
git push origin $COMMIT:$BRANCH
78 changes: 0 additions & 78 deletions .github/workflows/sync-upstream-advisories.yml

This file was deleted.

37 changes: 0 additions & 37 deletions .github/workflows/validate.yaml

This file was deleted.

4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
Tar = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53"

[compat]
julia = "1.11"
CodecZlib = "0.7.8"
DataStructures = "0.19.0"
Markdown = "1.11.0"
Pkg = "1.11.0"
Tar = "1.10.0"
TimeZones = "1.22.0"
julia = "1.11"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
73 changes: 73 additions & 0 deletions advisories/published/2025/DONOTUSEJLSEC-0000-3pwil8p118owt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
```toml
schema_version = "1.7.3"
id = "DONOTUSEJLSEC-0000-3pwil8p118owt"
modified = 2025-09-22T21:31:21.347Z
aliases = ["GHSA-4g68-4pxg-mw93", "CVE-2025-52479"]

[[affected]]
pkg = "HTTP"
ranges = ["<= 1.10.16"]
[[affected]]
pkg = "URIs"
ranges = ["< 1.6.0"]

[database_specific.source]
id = "GHSA-4g68-4pxg-mw93"
modified = "2025-06-24T23:01:25Z"
published = "2025-06-24T23:01:25Z"
imported = "2025-09-22T21:31:21.283Z"
url = "https://api.github.com/repos/JuliaWeb/HTTP.jl/security-advisories/GHSA-4g68-4pxg-mw93"
html_url = "https://github.com/JuliaWeb/HTTP.jl/security/advisories/GHSA-4g68-4pxg-mw93"
```

# CR/LF injection in URIs.jl (also affects HTTP.jl)

### Description

The URIs.jl and HTTP.jl packages allowed the construction of URIs containing CR/LF characters. If user input was not otherwise escaped or protected, this can lead to a CRLF injection attack.

With this simple Julia code, you can inject a custom header named `Foo` with the value `bar`:

``` julia
import HTTP

HTTP.get("http://localhost:1337/ HTTP/1.1\r\nFoo: bar\r\nbaz:")
```

The server will receive the request like this:

```
➜ ncat -klp 1337
GET / HTTP/1.1
Foo: bar <-- injected header!
baz: HTTP/1.1
Host: locahost:1337
Accept: */*
User-Agent: HTTP.jl/1.11.5
Content-Length: 0
Accept-Encoding: gzip
```

### Impact

Inject headers or inject data to the request body and cause “HTTP response splitting”.

### Patches

Users of HTTP.jl should upgrade immediately to HTTP.jl v1.10.17. All prior versions are vulnerable.

Users of URIs.jl should upgrade immediately to URIs.jl v1.6.0. All prior versions are vulnerable.

The check for valid URIs is now in the URI.jl package, and the latest version of HTTP.jl incorporates that fix.

### Workarounds

Manually validate any URIs before passing them on to functions in this package.

### References

Fixed by: https://github.com/JuliaWeb/URIs.jl/pull/66 (which is available in URIs.jl v1.6.0).

### Credits

Thanks to *splitline* from the DEVCORE Research Team for reporting this issue.
79 changes: 79 additions & 0 deletions scripts/assign_ids_and_dates.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using AdvisoryDB
using Dates: Dates, DateTime
using TimeZones: TimeZones, ZonedDateTime

function main()
all_advisories_path = joinpath(@__DIR__, "..", "advisories")
published_advisories_path = joinpath(@__DIR__, "..", "advisories", "published")

# First look through all advisories for the latest identifier
# TODO: We could use a lock/mutex of the form of a sentinel upstream branch here
year = Dates.year(Dates.now(Dates.UTC))
last_id = 0
for (root, _, files) in walkdir(all_advisories_path), file in files
AdvisoryDB.is_jlsec_advisory_path(joinpath(root, file)) || continue
prefix = string(AdvisoryDB.PREFIX, "-", year, "-")
startswith(file, prefix) || continue
last_id = max(last_id, something(tryparse(Int, chopprefix(chopsuffix(file, ".md"), prefix)), 0))
end

# Then go through the published advisories and ensure all IDs are assigned
# and that the dates accurately match the commit dates
n_updated = 0
for (root, _, files) in walkdir(published_advisories_path), file in files
path = joinpath(root, file)
AdvisoryDB.is_jlsec_advisory_path(path) || continue
advisory = AdvisoryDB.parsefile(path)
updated = false
if startswith(advisory.id, string(AdvisoryDB.PREFIX, "-0000-"))
last_id += 1
advisory.id = string(AdvisoryDB.PREFIX, "-", year, "-", last_id)
updated = true
newpath = joinpath(root, string(advisory.id, ".md"))
@info "moving $file to $(advisory.id).md"
success(`git mv $path $newpath`) || run(`mv $path $newpath`)
path = newpath
modified = published = Dates.now(Dates.UTC)
else
git_modified = readchomp(`git log -1 --format="%ad" --date=iso-strict -- $path`)
modified = isempty(git_modified) ? Dates.now(Dates.UTC) : DateTime(ZonedDateTime(git_modified), Dates.UTC)
git_published = readchomp(`git log --format="%ad" --date=iso-strict --diff-filter=A -- $path`)
published = isempty(git_published) ? modified : DateTime(ZonedDateTime(git_published), Dates.UTC)
end
if something(advisory.withdrawn, typemin(DateTime)) > advisory.modified
# If the withdrawn date is _after_ the previously stored modified time, then it's a new modification
# The effective time of the widthdraw will be upon publication to this repo — the new modified time
advisory.withdrawn = modified
advisory.modified = modified
updated = true
end
if abs(advisory.modified - modified) > Dates.Minute(10)
advisory.modified = modified
updated = true
end
if abs(something(advisory.published, DateTime(0)) - published) > Dates.Minute(10)
advisory.published = published
updated = true
end

if updated
# TODO: we could do better by applying a git diff that only includes the semantically meaningful parts
@info "writing $(advisory.id)"
open(path, "w") do io
print(io, advisory)
end
n_updated += 1
end
end

@info "updated $n_updated advisories"
io = haskey(ENV, "GITHUB_OUTPUT") ? open(ENV["GITHUB_OUTPUT"], "w") : stdout
println(io, "changes=", n_updated > 0)
if n_updated > 0
println(io, "title=[automated] assign id/timestamp $n_updated advisories")
end
end

if abspath(PROGRAM_FILE) == @__FILE__
main()
end
Loading
Loading