docs: add SECURITY.md and CONTRIBUTING.md
SECURITY.md: private reporting via GitHub advisories with an email fallback, a what-to-include checklist, response and disclosure policy, a scope section (what is and is not a vulnerability, including stealth and opt-in flags), third-party dependency handling, and the in-process security model (V8 watchdog, CLI deadline, panic safety, default SSRF egress block) with the note that it complements rather than replaces OS-level isolation. Modeled on the Electron, Node, and Puppeteer policies. CONTRIBUTING.md: code of conduct, an issue-first submission policy, build and test workflow (nextest not cargo test, the 33/33 obstacle course gate), the pre-PR checklist with performance as a hard constraint, commit and PR conventions, and bug-report expectations. Points at AGENTS.md for the deeper engine details instead of duplicating them.
This commit is contained in:
150
CONTRIBUTING.md
Normal file
150
CONTRIBUTING.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Contributing to Obscura
|
||||
|
||||
Thanks for your interest in Obscura. This guide covers how to build, test, and
|
||||
submit changes. For the deeper, non-obvious engine details (architecture,
|
||||
gotchas, robustness invariants), read [AGENTS.md](AGENTS.md) first; this file
|
||||
does not repeat it.
|
||||
|
||||
## Code of conduct
|
||||
|
||||
Be respectful and constructive. We want Obscura to be a welcoming project, so
|
||||
keep discussion focused on the work and assume good faith. Harassment or abuse
|
||||
is not tolerated.
|
||||
|
||||
## Before you start
|
||||
|
||||
For anything beyond a minor documentation fix, **please open an issue first** (or
|
||||
comment on an existing one) and say you intend to work on it. This lets us give
|
||||
early feedback and avoids two people building the same thing or a PR that does
|
||||
not fit the project's direction.
|
||||
|
||||
A few notes to keep the project maintainable:
|
||||
|
||||
- **Link an issue.** PRs without a linked issue or prior discussion may be
|
||||
closed, except for small doc fixes.
|
||||
- **Human oversight required.** AI-assisted contributions are fine, but
|
||||
low-quality or unreviewed agent output will be closed. Understand and test
|
||||
what you submit.
|
||||
- New to the codebase? Look for issues labeled `good first issue`.
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
cargo build --release # binary at ./target/release/obscura
|
||||
```
|
||||
|
||||
- The first build compiles V8 from source: roughly 5 minutes and a few GB of
|
||||
disk. Incremental builds are seconds.
|
||||
- Iterating on one crate? Scope it: `cargo build -p obscura-cli`.
|
||||
- **Stealth** (`--features stealth`) pulls in BoringSSL through CMake, so `cmake`
|
||||
must be installed. The default build uses rustls and needs neither CMake nor
|
||||
OpenSSL.
|
||||
- If the vendored OpenSSL build hits an AVX-512 assembler error on your host,
|
||||
build with `OPENSSL_NO_VENDOR=1`.
|
||||
|
||||
## Testing
|
||||
|
||||
Run tests with **`cargo nextest`, not `cargo test`**:
|
||||
|
||||
```bash
|
||||
cargo nextest run --workspace # or -p <crate> while iterating
|
||||
```
|
||||
|
||||
`cargo test` runs the whole test binary in one process, but the engine holds a
|
||||
single V8 isolate per process, so the runtime tests fail under it. `nextest`
|
||||
runs each test in its own process, which is the only supported way.
|
||||
|
||||
The authoritative behavioral gate is the **obstacle course** in the companion
|
||||
repo [`obscura-benchmark`](https://github.com/h4ckf0r0day/obscura-benchmark)
|
||||
(33 capability and speed stages, must stay 33/33):
|
||||
|
||||
```bash
|
||||
OBSCURA_BIN=./target/release/obscura python3 obstacle-course/run.py --runs 1 --warmup 0
|
||||
```
|
||||
|
||||
It serves local fixtures, so it is deterministic and offline.
|
||||
|
||||
## Before you open a PR
|
||||
|
||||
For any code change:
|
||||
|
||||
1. `cargo build --release` (or `-p <crate>`) compiles clean.
|
||||
2. `cargo nextest run` passes for the crates you touched.
|
||||
3. The obstacle course still reports **33/33**.
|
||||
4. **Performance is a hard constraint.** Obscura is roughly 12x faster and uses
|
||||
about 6x less memory than headless Chrome on framework pages. Keep the native
|
||||
Rust fast paths and add a JS fallback only for real spec edge cases. If your
|
||||
change could affect performance, benchmark old vs new interleaved, min-of-N
|
||||
(the noise floor is about plus or minus 10%).
|
||||
5. For stealth changes, re-test with `--stealth`. A non-stealth binary does not
|
||||
exercise the `wreq` path.
|
||||
|
||||
Keep ops panic-safe: a panic in an op must degrade to a null result, never
|
||||
unwind into V8's FFI frame. Do not remove the robustness guards described in
|
||||
AGENTS.md (the V8 watchdog, the `tree.rs` reparenting guards, the CLI deadline).
|
||||
|
||||
Do not bulk-run `cargo fmt`. The tree is not rustfmt-clean, so a blanket format
|
||||
produces a large unrelated diff. Match the surrounding style in the files you
|
||||
edit. Comments should explain non-obvious "why", not restate the code.
|
||||
|
||||
## Commit messages
|
||||
|
||||
Keep them short and factual: what changed and why. We use a lightweight
|
||||
`type(scope): summary` style, matching the existing history:
|
||||
|
||||
```
|
||||
fix(cdp): honor text selection on Backspace and typing
|
||||
|
||||
Backspace trimmed the last character and typing always appended, ignoring
|
||||
any selection. Both now respect a non-collapsed selection.
|
||||
|
||||
Fixes #316.
|
||||
```
|
||||
|
||||
- `type` is one of `fix`, `feat`, `docs`, `test`, `perf`, `chore`. The `scope`
|
||||
is optional and lowercase (for example `cdp`, `js`, `net`, `stealth`, `cli`).
|
||||
- No em dashes. Use commas, periods, or restructure the sentence.
|
||||
- No AI-generated filler ("This commit improves...", "As an AI...").
|
||||
- Do not add `Co-Authored-By` lines or list yourself as a co-author.
|
||||
|
||||
## Pull requests
|
||||
|
||||
- All submissions are reviewed; a maintainer merges after approval.
|
||||
- Keep the diff small and readable. One logical change per PR. Split large
|
||||
contributions into several PRs.
|
||||
- Reference the issue the PR closes, and say how you verified it (the test or
|
||||
repro that now passes).
|
||||
|
||||
## Reporting bugs
|
||||
|
||||
Open an issue with enough detail to reproduce:
|
||||
|
||||
- The obscura version or commit, plus OS and architecture.
|
||||
- A repro: a URL, an `--eval` snippet, or a short CDP sequence.
|
||||
- What you expected and what actually happened.
|
||||
- If it is a rendering or compatibility issue, whether headless Chrome behaves
|
||||
the same. Anti-bot, CAPTCHA, and login walls block headless Chrome too from a
|
||||
datacenter IP, so those are not engine bugs.
|
||||
|
||||
Multi-statement `--eval` that starts with `const` returns `null` (V8 gives
|
||||
`const` an empty completion value). Wrap repro snippets in an IIFE:
|
||||
`(function(){ ...; return result; })()`.
|
||||
|
||||
**Security issues:** do not open a public issue. See [SECURITY.md](SECURITY.md)
|
||||
for private reporting.
|
||||
|
||||
## Scope and direction
|
||||
|
||||
Obscura targets web scraping and AI-agent automation, and is heading toward a
|
||||
hosted cloud scraping service. The priorities are real-world render success and
|
||||
robustness (no crashes or hangs). Conformance and new Web APIs are welcome when
|
||||
they do not regress performance or stability.
|
||||
|
||||
The stealth features are privacy-first anti-fingerprinting: they present a
|
||||
normal, consistent browser identity so ordinary automation is not singled out.
|
||||
Contributions that add detection-evasion for abusive purposes are out of scope.
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree that your contributions are licensed under the
|
||||
[Apache License 2.0](LICENSE), the same license as the project.
|
||||
109
SECURITY.md
Normal file
109
SECURITY.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Security Policy
|
||||
|
||||
The Obscura project takes security seriously. Obscura runs real, untrusted
|
||||
JavaScript from arbitrary web pages through V8, so we appreciate your efforts to
|
||||
responsibly disclose what you find and will work with you to address it.
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
**Please do not report security issues through public GitHub issues, pull
|
||||
requests, or discussions.**
|
||||
|
||||
Report a vulnerability privately through GitHub: go to the repository's
|
||||
**Security** tab and click [**Report a vulnerability**](https://github.com/h4ckf0r0day/obscura/security/advisories/new)
|
||||
to open a private advisory.
|
||||
|
||||
If you cannot use GitHub advisories, email **hello@obscura.sh** with "security"
|
||||
in the subject line.
|
||||
|
||||
### What to include
|
||||
|
||||
To help us triage quickly, please provide as much of the following as you can:
|
||||
|
||||
- Type of issue (SSRF, hang or crash / denial of service, memory safety,
|
||||
cross-session data exposure, etc.).
|
||||
- The obscura version or commit, plus OS and architecture.
|
||||
- The location of the affected code (file path and commit, or a direct link).
|
||||
- Any special configuration or flags required to reproduce.
|
||||
- Step-by-step instructions: a page, `--eval` snippet, or CDP sequence that
|
||||
triggers it.
|
||||
- Proof-of-concept code if you have it, and the impact you think it has.
|
||||
|
||||
## Our response
|
||||
|
||||
We will send a response indicating the next steps in handling your report,
|
||||
normally within 3 business days. We will keep you informed of progress toward a
|
||||
fix, and may ask for additional information. We practice coordinated disclosure:
|
||||
please give us a reasonable window to ship a fix before any public writeup, and
|
||||
we will credit you in the advisory unless you ask us not to.
|
||||
|
||||
If you do not receive an acknowledgement within 6 business days, please follow
|
||||
up by email to make sure we received the report.
|
||||
|
||||
## Scope
|
||||
|
||||
Obscura is a powerful tool for browser automation, scraping, and inspection. It
|
||||
is the responsibility of the calling code and the operator to use it safely. The
|
||||
security boundaries Obscura is meant to hold, and which are in scope:
|
||||
|
||||
- **Egress / SSRF control.** Page content reaching loopback, RFC 1918, or
|
||||
link-local addresses without `--allow-private-network` being set.
|
||||
- **Availability.** A page, script, or DOM structure that defeats the V8
|
||||
termination watchdog, the CLI hard deadline, or the panic guards and so hangs
|
||||
or aborts the process.
|
||||
- **Memory safety** in Obscura's own `unsafe` Rust or in an op that bridges JS
|
||||
to Rust.
|
||||
- **Process and data integrity.** A page that escapes the intended op surface,
|
||||
corrupts another page's state, or reads data across origins or sessions it
|
||||
should not (cookies, storage, response bodies).
|
||||
- **TLS / identity correctness** issues that weaken or misrepresent a connection
|
||||
in a way the user did not request.
|
||||
|
||||
The following are **not** vulnerabilities. We welcome feedback on them as
|
||||
feature requests, but they will not be treated as security issues:
|
||||
|
||||
- **Stealth / anti-fingerprinting behavior.** Presenting a normal, consistent
|
||||
browser fingerprint is the intended, privacy-first design of stealth mode.
|
||||
Requests to add detection-evasion for abusive purposes are out of scope.
|
||||
- **Anything behind an explicit opt-in,** such as reaching a private address
|
||||
when `--allow-private-network` (or `OBSCURA_ALLOW_PRIVATE_NETWORK=1`) is set,
|
||||
or behavior that requires local access to the machine running Obscura.
|
||||
- **Resource use from a page you chose to load** that stays within the watchdog
|
||||
and deadline limits. Slow pages are not a vulnerability.
|
||||
- **Findings against the companion benchmark repo fixtures** rather than the
|
||||
engine itself.
|
||||
|
||||
## Third-party dependencies
|
||||
|
||||
Report vulnerabilities in third-party crates to their respective maintainers (or
|
||||
the [RustSec advisory database](https://rustsec.org/)). The workspace is gated
|
||||
by `cargo deny` via `deny.toml`. If a dependency advisory affects Obscura's own
|
||||
behavior, let us know so we can pin or patch.
|
||||
|
||||
## Security model and operator responsibilities
|
||||
|
||||
Obscura executes untrusted page JavaScript **in process** through V8. Its
|
||||
in-process hardening reduces blast radius but is not a substitute for operating
|
||||
system isolation:
|
||||
|
||||
- The **V8 termination watchdog** terminates the isolate from a separate thread
|
||||
when synchronous script work overruns, because `tokio` timeouts only cancel at
|
||||
await points.
|
||||
- The **CLI process-level hard deadline** is an absolute backstop for a hang
|
||||
inside a Rust op that neither `tokio` nor `terminate_execution` can interrupt.
|
||||
- **Panic safety:** ops are wrapped so a panic degrades to a null result instead
|
||||
of aborting the process inside V8's FFI frame; `panic = "unwind"` is pinned in
|
||||
the release profile.
|
||||
- The **default network egress policy** blocks private and loopback ranges.
|
||||
|
||||
These measures protect availability and limit egress. They do **not** claim to
|
||||
contain a hostile page that achieves native code execution through a V8 exploit.
|
||||
If you run Obscura against untrusted or adversarial input at scale, run it under
|
||||
OS-level isolation (a container or VM) with a restricted network, the same way
|
||||
you would run headless Chrome. Per-user container isolation is planned for the
|
||||
hosted service so that one session cannot affect another.
|
||||
|
||||
## Supported versions
|
||||
|
||||
Security fixes land on `main` and ship in the next release. Please test reports
|
||||
against the latest release or `main`.
|
||||
Reference in New Issue
Block a user