Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
59008c7
SecurityUtils.secure_compare runs in emitted Ruby
bunnykong Oct 5, 2026
dc3e11e
Slim: inline text continues on deeper lines; XHTML doctypes
Oct 6, 2026
274226c
Expand *rest class macros that peel options with extract_options!
Oct 6, 2026
df59341
*rest macro expansion refuses splats and keys it cannot read
Oct 6, 2026
e742692
Filter macro `only:`/`except:` refuse actions they cannot read
Oct 6, 2026
8ce4eeb
emit-and-run harness removes its scratch trees
Oct 6, 2026
a47036f
Drop CR/LF headers in Spinel servers and strip redirect and dispositi…
gregmolnar Oct 5, 2026
64d6d6d
Stack AR, header, redirect, cookie, and CSRF guards on #461
cursoragent Oct 6, 2026
d3b02ac
Keep implicit CSRF default off and pin overlays
cursoragent Oct 6, 2026
e6a993e
Keep last_n/first_n in the query overlay
cursoragent Oct 6, 2026
adc088e
Pin first/last(n) so last_n survives emit
cursoragent Oct 6, 2026
0e344dc
Keep header and order guards portable across targets
cursoragent Oct 6, 2026
988c6af
Merge pull request #469: Slim: inline text continues on deeper lines;…
rubys Oct 6, 2026
ea9f468
Merge pull request #470: Expand *rest class macros that peel options …
rubys Oct 6, 2026
3a7fe72
Merge pull request #474: emit-and-run harness removes its scratch trees
rubys Oct 6, 2026
2b25be2
Cut CI runner minutes inside existing jobs
cursoragent Oct 6, 2026
f17b30a
Drop unstable profile rustflags from unit CI
cursoragent Oct 6, 2026
02bdf31
Keep HeaderStore and redirect guards portable
cursoragent Oct 6, 2026
4ff062d
Merge rubys/roundhouse main into security meta-PR
cursoragent Oct 6, 2026
508c518
Ledger Bar B untyped ceiling for security helpers
cursoragent Oct 6, 2026
d424205
Default HttpOnly and honor explicit Secure on cookies
cursoragent Oct 6, 2026
8caca0c
Strip interior tabs before classifying redirect hosts
cursoragent Oct 6, 2026
7168cdd
Allow listed RANDOM() as an order function term
cursoragent Oct 6, 2026
a37ca09
Restore disk filename after send_data overwrites disposition
cursoragent Oct 6, 2026
c222342
Honor SameSite options and pair None with Secure
cursoragent Oct 6, 2026
52743bc
Tighten Soft Bar B ratchet to 299
thomasklemm Oct 6, 2026
7bfaf25
Merge rubys/roundhouse main into security meta-PR
cursoragent Oct 6, 2026
34eac00
Expand interpolatable class_eval macros at ingest
cursoragent Oct 6, 2026
2581634
Cascade has_one dependent: :destroy through before_destroy
cursoragent Oct 6, 2026
7252e12
Pin Kaminari DISTINCT and GROUP BY total_count
cursoragent Oct 6, 2026
e0d81ab
Fix kaminari DISTINCT overlay and has_one destroy shape pin
cursoragent Oct 6, 2026
3cae3f7
Name pagination as LIMIT/OFFSET page arithmetic
cursoragent Oct 6, 2026
01805f3
Pin Relation DISTINCT and GROUP BY result-set count
cursoragent Oct 6, 2026
ac77415
Rename default_per_page and restore pagination emit-and-run
cursoragent Oct 6, 2026
9e7dfc4
Count DISTINCT/GROUP BY through a scoped Relation
cursoragent Oct 6, 2026
b5d87cd
Split class_eval expansion and fail closed on required keywords
cursoragent Oct 6, 2026
2a3f0cd
Accept page: and per_page: on paginate
cursoragent Oct 6, 2026
c0d7973
Pin leftover interpolations and fill App/paginate CI holes
cursoragent Oct 6, 2026
e781566
Pin leftover interpolated associations through on_load
cursoragent Oct 6, 2026
39ba121
Pin leftover interpolated macros with emit-and-run
cursoragent Oct 6, 2026
b553a70
Record declined has_markdown expansion in the Writebook inventory
cursoragent Oct 6, 2026
1691d6c
Keep leftover interpolated macros as a strict ingest error
cursoragent Oct 6, 2026
65a0b9c
Decline class_eval expansion on omitted keywords and shadows
cursoragent Oct 6, 2026
c4485f8
Ledger paginate kwargs in the runtime untyped ceiling
cursoragent Oct 6, 2026
5f2d89c
Ledger paginate kwargs against the 299 untyped ratchet
cursoragent Oct 6, 2026
b911b6f
The spinel tree names the app source each statement came from
rubys Oct 6, 2026
f32653e
Run extra-language SDKs on schedule, not every main push
cursoragent Oct 6, 2026
c49721b
Say unknown project.rs shapes keep the Ruby floor
cursoragent Oct 6, 2026
7c9f93e
Drop break from sanitize_location for Go and TypeScript
cursoragent Oct 6, 2026
90fac3a
Split limit/offset nil assignment for Spinel
cursoragent Oct 6, 2026
86fd4a1
Honor explicit httponly: false on Rack cookies
cursoragent Oct 6, 2026
3b66d8a
Type paginate params as Integer | String | nil
cursoragent Oct 6, 2026
b6b1864
Drop nil header writes without calling length
cursoragent Oct 6, 2026
f90c14b
Hill climb: Writebook as the forcing fixture for class-body declarati…
thomasklemm Oct 6, 2026
0e19bb4
Merge rubys/roundhouse main into security meta-PR
cursoragent Oct 6, 2026
aa78a00
Default HttpOnly when signed options omit the flag
cursoragent Oct 6, 2026
71f059b
A method's source marker goes above its def
rubys Oct 6, 2026
bd997d6
[SECURITY] Stacked meta-PR: AR SQLi, CRLF headers, open redirect, coo…
thomasklemm Oct 6, 2026
f8fa710
Merge pull request #441 from bunnykong/secure-compare-runtime
bunnykong Oct 6, 2026
37bb4c5
Permanent cookies go out with an expiry
rubys Oct 6, 2026
68bb3ee
Fix String#bytes integer values and block typing (#434)
dchuk Oct 6, 2026
6b4f465
Fix a typo in SECURITY.md
bunnykong Oct 6, 2026
3a7b3c1
Unblock main unit shards after String#bytes (#434)
cursoragent Oct 6, 2026
6741d8a
Unblock main unit shards after String#bytes (#434)
thomasklemm Oct 6, 2026
d67de85
Reuse one untyped view lowering for construct-to-library
cursoragent Oct 6, 2026
0952eed
Fuse independent post-analyze walks and skip extra controller typing
cursoragent Oct 6, 2026
9c87909
Skip extra Arel retypes and drop Debug keys from union sort
cursoragent Oct 6, 2026
abc8425
Skip Debug fingerprints and fuse more post-analyze walks
cursoragent Oct 6, 2026
e4706f7
Skip extra typing in test_module_to_library
cursoragent Oct 6, 2026
d4a9405
Fuse remaining independent context-heavy post-analyze walks
cursoragent Oct 6, 2026
b616ec2
Fuse remaining independent post-analyze walks
cursoragent Oct 6, 2026
a4bc7f8
Fuse leftover sequential post-analyze walks
cursoragent Oct 6, 2026
0429090
Match analyzer unions to structural variant order
cursoragent Oct 6, 2026
96084b7
Cut duplicate analyzer and controller lowering work
cursoragent Oct 6, 2026
1ee773e
Skip intermediate view typing in the analyzer fixpoint
cursoragent Oct 6, 2026
03f2ce4
Emit rust Value-shaped unions without E0308/E0599
cursoragent Oct 6, 2026
bcbff17
Harvest model returns before typing controllers
cursoragent Oct 6, 2026
2c8cbcd
Skip views and tests on the first analyzer pass
cursoragent Oct 6, 2026
f9f59a8
Skip extra construct-to-library typing passes
cursoragent Oct 6, 2026
65160db
Retype tests after production until helper chains settle
cursoragent Oct 6, 2026
74493c7
Skip untyped view/test unify walks during production
cursoragent Oct 6, 2026
3c36c61
Address CodeRabbit findings on the ingest→lower PR
cursoragent Oct 6, 2026
6eccbd0
Fix view-only Alba absorb and rust Value to_s quotes
cursoragent Oct 6, 2026
2524431
Keep format-suffix wraps visible to host rewrite
cursoragent Oct 6, 2026
7f5e4c7
Deref Emitted at string_bytes current_dir sites
cursoragent Oct 6, 2026
08028c6
Stringify form_with method before the typed helper
cursoragent Oct 6, 2026
80bc159
Port rust-only Value-union UFCS from view-helpers types
cursoragent Oct 6, 2026
4eaea33
Restamp views after helper returns absorb view sites
cursoragent Oct 6, 2026
1a736f5
Fix ActionController rust emit for compare cargo check
cursoragent Oct 6, 2026
368b230
Speed up ingest → lowered IR (#477)
thomasklemm Oct 6, 2026
c4642c2
Speed up Swift compare-extra (same check)
thomasklemm Oct 6, 2026
a7c4d35
Fix extra-language emit for HeaderStore typing
cursoragent Oct 6, 2026
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
124 changes: 87 additions & 37 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ on:
value: ${{ jobs.compact-required.outputs.passed == 'true' && jobs.assemble-site.outputs.ready == 'true' }}

# Separate from the full-ci caller's lock: workflow_call inherits its context.
# Push-to-main now runs full coverage; cancel superseded SHAs so merge trains
# do not stack 50-job matrices. Scheduled/manual full-ci keeps its own lock.
# Push-to-main is Ruby+Spinel, not the extra-language matrix; cancel
# superseded SHAs so merge trains do not stack. Scheduled/manual full-ci
# is the extra-SDK ledger and keeps its own lock.
concurrency:
group: validation-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' || github.event_name == 'push' }}
Expand Down Expand Up @@ -113,9 +114,7 @@ jobs:
env:
WRITEBOOK_ROOT: /tmp/writebook
WRITEBOOK_INVENTORY_REPORT: writebook-inventory-current.json
run: |
cargo build --locked --release --bin roundhouse
cargo test --locked --test writebook --release -- --ignored --nocapture
run: cargo test --locked --release --bin roundhouse --test writebook -- --ignored --nocapture
- name: Save complete check report
id: report
if: always() && (steps.reuse.outcome != 'success' || steps.reuse.outputs.hit != 'true')
Expand Down Expand Up @@ -310,16 +309,19 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: python3 scripts/ci-reuse.py probe --job store-check --input fixtures/store
# Debug, not release: the analyzer claim is the same IR. On PR
# 37439350975 this job spent 95s of 113s compiling a release
# binary for a check that finishes in seconds.
- name: cargo build
id: build
if: steps.reuse.outcome != 'success' || steps.reuse.outputs.hit != 'true'
run: cargo build --locked --release --bin roundhouse
run: cargo build --locked --bin roundhouse
- name: The analyzer reports no errors, no warnings and no ingest gaps on the store
id: check
if: steps.reuse.outcome != 'success' || steps.reuse.outputs.hit != 'true'
run: |
set -euo pipefail
target/release/roundhouse check --continue fixtures/store 2>&1 | tee /tmp/store-check.txt
target/debug/roundhouse check --continue fixtures/store 2>&1 | tee /tmp/store-check.txt
grep -E "^roundhouse-check: .* 0 error\(s\), 0 warning\(s\), 0 gap-attributed note\(s\), 0 survey gap\(s\)" /tmp/store-check.txt
- name: Record actual successful execution
id: execution
Expand Down Expand Up @@ -431,6 +433,7 @@ jobs:
# Preprocess each time: Spinel uses conditional __has_include headers.
SCCACHE_DIRECT: "false"
SCCACHE_IDLE_TIMEOUT: "0"
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
with:
Expand Down Expand Up @@ -579,33 +582,43 @@ jobs:
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ env.MRI_RUBY }}
- name: Install the gem the overlay escape surface uses
run: gem install rails-html-sanitizer --no-document
# The native Date reference uses ActiveRecord against in-memory
# SQLite. Fixture generation ships source, not its installed gems.
- name: Install ActiveRecord for the native Date reference
run: gem install activerecord -v '~> 8.1.0' --no-document
# `tests/emit_and_run.rs` and `tests/relation_runtime_cruby.rs`
# run the emitted Ruby tree, whose database layer is the sqlite3
# gem. The second skipped without it and passed: before this step
# the unit job ran it as a no-op. The first refuses to skip.
# libvips42: `tests/vips_loader_policy.rs` boots an emitted variant
# app and asks `Vips.vips_foreign_find_load` after the app's loader
# policy. CRuby binds through FFI, so the library is enough; headers
# are the compiled Spinel job.
- name: System libvips for the emitted ruby-vips processor
run: |
"$GITHUB_WORKSPACE/scripts/ci-apt-install" libvips42
# One gem process: three sequential `gem install` steps were paying
# RubyGems startup separately for the same default gem path.
#
# Campfire launcher regressions (`tests/ci_campfire_optimization_test.py`,
# invoked from `tests/ci_policy_workflow.rs`) preload
# `scripts/campfire-test-bcrypt.rb`, which `require "bcrypt"`. A
# runner without the gem fails those tests; a dev box that has it
# hides the gap.
# rails-html-sanitizer — `tests/overlay_sanitize_autolink.rs` shells
# out to ruby and loads the CRuby overlay's escape surface. Without
# the gem the overlay falls back to the shared scanner (which refuses
# markup by design) and the test fails naming this step.
# setup-ruby, not the runner's system ruby: `gem install` against
# system ruby is a Gem::FilePermissionError, and the test asserts
# EXACT sanitizer output, so the ruby it runs on is part of the
# assertion. 3.4 is the version campfire-conformance pins.
#
# `tests/vips_loader_policy.rs` boots an emitted variant app and
# asks `Vips.vips_foreign_find_load` after the app's loader policy.
# That require is ruby-vips over the system libvips: without both,
# the test dies on `cannot load such file -- vips` while a machine
# that already has the gem hides the gap. CRuby binds through FFI,
# so libvips42 is enough; headers are the compiled Spinel job.
- name: System libvips for the emitted ruby-vips processor
run: sudo apt-get update -qq && sudo apt-get install -y -qq libvips42
# activerecord — the native Date reference uses ActiveRecord against
# in-memory SQLite. Fixture generation ships source, not its gems.
#
# sqlite3 — `tests/emit_and_run.rs` and `tests/relation_runtime_cruby.rs`
# run the emitted Ruby tree. The second skipped without the gem and
# passed: before this install the unit job ran it as a no-op.
#
# bcrypt — Campfire launcher regressions
# (`tests/ci_campfire_optimization_test.py`) preload
# `scripts/campfire-test-bcrypt.rb`. A runner without the gem fails
# those tests; a dev box that has it hides the gap.
#
# ruby-vips — pairs with libvips42 above; without the gem the vips
# loader test dies on `cannot load such file -- vips`.
- name: Install gems used by emitted Ruby and Campfire harness tests
run: gem install sqlite3 bcrypt ruby-vips --no-document
run: |
gem install --no-document rails-html-sanitizer sqlite3 bcrypt ruby-vips
gem install --no-document activerecord -v '~> 8.1.0'
# Bounded build → run → free waves: every --all-targets identity still
# goes through Cargo (lib, bins, each integration target). Finished
# integration executables and their own split-DWARF sidecars are freed
Expand Down Expand Up @@ -636,8 +649,9 @@ jobs:
run: |
python3 scripts/ci-resources.py --out "$RUNNER_TEMP/unit-resources/bench" -- \
bash -euo pipefail -c '
test -x target/debug/emit_preview
for target in typescript crystal rust python elixir go kotlin swift csharp; do
cargo run --quiet --bin emit_preview -- --target "$target" fixtures/real-blog >/dev/null
target/debug/emit_preview --target "$target" fixtures/real-blog >/dev/null
done
'
- name: Upload unit resource samples
Expand Down Expand Up @@ -961,6 +975,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
continue-on-error: true
env:
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-rust
Expand Down Expand Up @@ -1084,7 +1100,8 @@ jobs:
# app's own hardening line.
# CRuby binds libvips through FFI; only compiled Spinel needs headers.
- name: System libvips
run: sudo apt-get update -qq && sudo apt-get install -y -qq libvips42 sqlite3
run: |
"$GITHUB_WORKSPACE/scripts/ci-apt-install" libvips42 sqlite3
- name: Cache the prepared oracle
id: oracle
uses: actions/cache@v6
Expand Down Expand Up @@ -1149,6 +1166,8 @@ jobs:
outputs:
artifact-id: ${{ steps.binary.outputs.artifact-id }}
execution: ${{ steps.result.outputs.status }}
env:
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-rust
Expand All @@ -1162,7 +1181,8 @@ jobs:
chmod +x spinel-dist/spinel spinel-dist/spin spinel-dist/spinel_rbs_extract
echo "$PWD/spinel-dist" >> $GITHUB_PATH
- name: System libvips + libsqlite3-dev + libjemalloc-dev
run: sudo apt-get update -qq && sudo apt-get install -y -qq libvips-dev libsqlite3-dev libjemalloc-dev
run: |
"$GITHUB_WORKSPACE/scripts/ci-apt-install" libvips-dev libsqlite3-dev libjemalloc-dev
- name: Fetch pinned once-campfire
run: |
curl -fsSL "https://codeload.github.com/basecamp/once-campfire/tar.gz/${CAMPFIRE_SHA}" -o /tmp/campfire.tar.gz
Expand Down Expand Up @@ -1301,6 +1321,7 @@ jobs:
ports: ['6379:6379']
env:
BUNDLE_PATH: vendor/bundle
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-rust
Expand Down Expand Up @@ -1329,7 +1350,8 @@ jobs:
# this program's allocator and `spin build` links `-ljemalloc`.
# The DEV package, not libjemalloc2: the runtime library LD_PRELOAD
# uses cannot be linked against.
run: sudo apt-get update -qq && sudo apt-get install -y -qq libvips-dev libsqlite3-dev libjemalloc-dev sqlite3
run: |
"$GITHUB_WORKSPACE/scripts/ci-apt-install" libvips-dev libsqlite3-dev libjemalloc-dev sqlite3
- name: Fetch pinned once-campfire
run: |
curl -fsSL "https://codeload.github.com/basecamp/once-campfire/tar.gz/${CAMPFIRE_SHA}" -o /tmp/campfire.tar.gz
Expand Down Expand Up @@ -1371,6 +1393,7 @@ jobs:
ports: ['6379:6379']
env:
BUNDLE_PATH: vendor/bundle
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-rust
Expand All @@ -1387,7 +1410,8 @@ jobs:
chmod +x spinel-dist/spinel spinel-dist/spin spinel-dist/spinel_rbs_extract
echo "$PWD/spinel-dist" >> $GITHUB_PATH
- name: System libvips + libsqlite3-dev + libjemalloc-dev
run: sudo apt-get update -qq && sudo apt-get install -y -qq libvips-dev libsqlite3-dev libjemalloc-dev sqlite3
run: |
"$GITHUB_WORKSPACE/scripts/ci-apt-install" libvips-dev libsqlite3-dev libjemalloc-dev sqlite3
- name: Fetch pinned once-campfire
run: |
curl -fsSL "https://codeload.github.com/basecamp/once-campfire/tar.gz/${CAMPFIRE_SHA}" -o /tmp/campfire.tar.gz
Expand Down Expand Up @@ -1881,6 +1905,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
continue-on-error: true
env:
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-rust
Expand Down Expand Up @@ -2029,6 +2055,19 @@ jobs:
if: matrix.target == 'swift'
run: |
"$GITHUB_WORKSPACE/scripts/ci-apt-install" libsqlite3-dev
- &swiftpm-cache
name: Cache SwiftPM checkouts
if: matrix.target == 'swift'
uses: actions/cache@v6
with:
# Cloned Hummingbird/NIO trees. Object files stay per-package in
# .build/; sharing those across emit dirs is not reliable.
path: |
~/.cache/org.swift.swiftpm
~/.swiftpm
key: swiftpm-${{ runner.os }}-${{ runner.arch }}-swift6.1-${{ hashFiles('src/emit/swift/package.rs') }}
restore-keys: |
swiftpm-${{ runner.os }}-${{ runner.arch }}-swift6.1-
- name: Install .NET (C#)
if: matrix.target == 'csharp'
uses: actions/setup-dotnet@v6
Expand Down Expand Up @@ -2094,7 +2133,11 @@ jobs:
run: cargo test --test framework_tests_kotlin -- --ignored --nocapture
- name: cargo test --test framework_tests_swift
if: ${{ !cancelled() && matrix.target == 'swift' }}
run: cargo test --test framework_tests_swift -- --ignored --nocapture
run: |
# scripts/compare then runs emit_preview; compiling it here reuses
# the libroundhouse just built for the test harness.
cargo build --bin emit_preview --quiet
cargo test --test framework_tests_swift -- --ignored --nocapture
- name: cargo test --test typescript_toolchain real_blog -- --ignored
if: ${{ !cancelled() && matrix.target == 'typescript' }}
run: cargo test --test typescript_toolchain real_blog -- --ignored --nocapture
Expand Down Expand Up @@ -2379,6 +2422,7 @@ jobs:
if: matrix.target == 'swift'
run: |
"$GITHUB_WORKSPACE/scripts/ci-apt-install" libsqlite3-dev
- *swiftpm-cache
- name: Install .NET (C#)
if: matrix.target == 'csharp'
uses: actions/setup-dotnet@v6
Expand Down Expand Up @@ -2513,6 +2557,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
continue-on-error: true
env:
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
Expand Down Expand Up @@ -2597,6 +2643,8 @@ jobs:
# 26 of its 30 minutes on 2026-09-12 (run 34725916085). A publish
# that times out four minutes short is a flake waiting to happen.
timeout-minutes: 60
env:
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-rust
Expand Down Expand Up @@ -2780,6 +2828,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
continue-on-error: true
env:
MAKEFLAGS: "-j4"
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ oracle: the same URL fetched from Rails and from each target must
produce the same response — emitted tests, a differential compare
against live Rails (DOM node for DOM node, JSON value for value), and
browser end-to-end tests for what a static diff can't reach — and
the full target matrix runs after merge to `main` and in scheduled
validation, with a Ruby floor and targeted additions on pull requests. →
the full target matrix runs in scheduled validation, with a Ruby floor
and targeted additions on pull requests (canonical `main` keeps Ruby
plus Spinel). →
[`--target`](docs/guide/transpile.md) · [targets](docs/guide/targets.md)
· [what of Rails comes through](docs/guide/rails-coverage.md) ·
[verifying](docs/guide/verifying.md)
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ from everyone.
- If you have Hardening ideas, found a weakness in tooling or low level
vulnerability, please open a public issue or pull request as usual.
- If you found a high level security issue that could be used to exploit a
compiled app and cause serious damage, please report privately throigh
compiled app and cause serious damage, please report privately through
[GitHub's private vulnerability
reporting](https://github.com/rubys/roundhouse/security/advisories/new).
Please include reproduction steps and the targets you checked and if you
Expand Down
Loading
Loading