Visitar URL original
feat(proxy): add deny_domain to block domains through the proxy by SequeI · Pull Request #1374 · nolabs-ai/nono · GitHub
Skip to content

feat(proxy): add deny_domain to block domains through the proxy - #1374

Merged
SequeI merged 2 commits into
mainfrom
denyDomain
Jul 7, 2026
Merged

SequeI merged 2 commits into
mainfrom
denyDomain

Conversation

@SequeI

@SequeI SequeI commented Jul 7, 2026 •

Copy link
Copy Markdown
Member

Linked Issue

Closes #1330

Summary

Adds --deny-domain CLI flag and deny_domain profile key to complement allow_domain. Users can now say "allow everything except these domains" without enumerating an allowlist. Deny rules are evaluated before the allowlist, support wildcard subdomains (*.example.com), and activate the proxy on their own. Conflicts with --allow-net at parse time. Port-suffix warnings are emitted for deny entries consistent with allow-domain behavior.

Test Plan

Checklist

  • An issue exists and is linked above
  • All commits are signed-off, using DCO
  • All new code follows the project's coding standards (CLAUDE.md) and is covered by tests
  • Public-facing changes are paired with documentation updates
  • Release note has been added to CHANGELOG.md if needed

Adds --deny-domain CLI flag and deny_domain profile key to complement
allow_domain. Users can now say "allow everything except these domains"
without enumerating an allowlist. Deny rules are evaluated before the
allowlist, support wildcard subdomains (*.example.com), and activate the
proxy on their own. Conflicts with --allow-net at parse time. Port-suffix
warnings are emitted for deny entries consistent with allow-domain behavior.

Signed-off-by: Aleksy Siek <aleksy@alwaysfurther.ai>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

PR Review Summary

Size

Metric Value
Lines added +311
Lines removed -26
Total changed 337
Classification Large (> 300 lines)

Affected crates

  • crates/nono (core library) — careful review required. This is the security-critical sandbox primitive. A bug here bypasses OS-level isolation for every downstream user.
  • crates/nono-proxy — downstream consumers depend on this crate. API or behaviour changes will affect external callers; treat any breaking change with extra scrutiny.
  • crates/nono-cli — CLI changes. Verify argument parsing, flag documentation, and UX behaviour across supported platforms.

Blast radius — Moderate

This PR touches: source code,documentation


Updated automatically on each push to this PR.

@nogent-nolabs-ai nogent-nolabs-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ nogent could not produce a schema-conforming security review for this change (the model output failed canary/shape validation). A maintainer should review manually.

@SequeI
SequeI merged commit 3b207ee into main Jul 7, 2026
15 checks passed
@SequeI
SequeI deleted the denyDomain branch July 10, 2026 10:10
oscarmackjr-twg added a commit to OscarMackJr/nono that referenced this pull request Aug 15, 2026
Discussed 4 gray areas for the UPST12 divergence audit. Live scouting
contradicted several planning assumptions:

- window is 100 non-merge commits, not the ~40 the 260727-jkn map
  estimated (68 CODE / 15 DEPS / 11 CI / 6 DOCS)
- 20 commits touch the tool-sandbox surface, not the 7 refinement PRs
  named in REQUIREMENTS; 12 of them are entangled with other code
- deny_domain (nolabs-ai#1374) touches crates/nono/src/net_filter.rs, a core
  library file
- ~28 code commits map to none of v3.6's 12 requirements, several
  security-relevant

23 decisions captured (D-01..D-23). Headlines:

- Entangled commits get split verdicts with per-commit path-level
  dispositions. A blanket tool-sandbox defer would demonstrably drop
  PROF-02, PROF-03, a musl build fix and an 18-file seccomp refactor.
- Deferral boundary is an explicit module set (tool-sandbox/,
  command_policy.rs, lineage_cgroup.rs), re-measured each sync. Their
  union equals the directory-only set in this window by coincidence,
  not by rule - recorded as such.
- Per-commit residue accounting: every path marked absorb/defer/noise;
  an unbucketed path is a ledger defect. Structural mitigation for the
  cluster-isolation-can-be-empirically-false anti-pattern.
- deny_domain gets standalone proj/ADR-108-deny-domain-posture.md,
  settled in 108. Posture is ADAPT: deny layer only, never an allowlist
  substitute, so a deny-only profile still fails closed. ADR-86 is not
  breached (with_denied_hosts takes a caller-supplied list; the library
  gains mechanism, not policy).
- Cluster-first granularity, per-commit rows only for will-sync/split.
  File-set noise classification with commit-prefix as cross-check (the
  two disagree on ~6 commits here).
- Phase 108's SC4 cannot be satisfied as written. Treated as a
  legitimate audit finding: the ledger reports the gap and proposes a
  new Phase 112 (Security + Residual Sync), operator-approved before
  Phase 109 planning.

Signed-off-by: Oscar Mack Jr <oscar.mack.jr@gmail.com>
Signed-off-by: oscarmackjr-twg <oscar.mack.jr@gmail.com>
oscarmackjr-twg added a commit to OscarMackJr/nono that referenced this pull request Aug 15, 2026
…-vs-adapt posture

Standalone ADR mirroring ADR-86/ADR-98, showing both options (full-sync-adopt
vs adapt-deny-layer-only) grounded in the live net_filter.rs code before
landing on the D-12 ADAPT recommendation: absorb deny_suffixes/
with_denied_hosts as additive library mechanism (ADR-86 compliant, caller-
supplied), but require the CLI-side network_policy.rs resolver to select a
fail-closed HostFilter construction whenever a profile carries deny_domain
without an explicit allow_domain, and reject upstream's auto-activate-proxy-
on-deny-alone trigger. Scoped to deny_domain only per D-13.

Signed-off-by: Oscar Mack Jr <oscar.mack.jr@gmail.com>
oscarmackjr-twg added a commit to OscarMackJr/nono that referenced this pull request Aug 15, 2026
Hand-verify requirement mapping (D-21) and actual-diff re-export scans for
all 12 NET cluster commits (proxy/network). 3b207ee (nolabs-ai#1374 deny_domain)
disposition cross-references ADR-108 instead of duplicating its analysis.

Signed-off-by: Oscar Mack Jr <oscar.mack.jr@gmail.com>
oscarmackjr-twg added a commit to OscarMackJr/nono that referenced this pull request Aug 15, 2026
…abs-ai#1374)

Task 1 of 109-01: HostFilter/ProxyFilter/ProxyConfig gain a caller-
supplied deny mechanism (deny_suffixes + with_denied_hosts), additive
and backward-compatible with the existing deny_hosts/DENY_HOSTS/
FilterResult::Deny* family. Deny is evaluated before the allowlist
(check_host step 1b) and always wins over allow. Per ADR-108, the
mechanism itself is policy-free caller-supplied data (ADR-86 intact);
the fail-closed CLI-side policy decision lands in Task 2/3.

- crates/nono/src/net_filter.rs: HostFilter.deny_suffixes field +
  with_denied_hosts() builder + check_host() step 1b wildcard-deny
  evaluation; 6 ported unit tests.
- crates/nono-proxy/src/filter.rs: ProxyFilter::with_denied_hosts()
  wrapping HostFilter::with_denied_hosts(); 2 tests.
- crates/nono-proxy/src/config.rs: ProxyConfig.denied_hosts field.
- crates/nono-proxy/src/server.rs: chain .with_denied_hosts() onto the
  proxy's sole filter-construction site.

Signed-off-by: Oscar Mack Jr <oscar.mack.jr@gmail.com>
oscarmackjr-twg added a commit to OscarMackJr/nono that referenced this pull request Aug 15, 2026
…ma (nolabs-ai#1374)

Task 2 of 109-01: mirrors the existing allow_domain/allow_proxy pattern
field-for-field to thread deny_domain through every layer it currently
exists at, per ADR-108's ADAPT posture.

- cli.rs: --deny-domain flag (deny_proxy: Vec<String>), NONO_DENY_DOMAIN
  env var, conflicts_with = "allow_net"; deny_proxy added to --config's
  conflicts_with_all (mirrors allow_proxy — otherwise `--config m.json
  --deny-domain evil.com` parses successfully with zero enforcement
  effect); has_proxy_flags() mirror.
- profile/mod.rs: NetworkConfig.deny_domain: Vec<String>, merged via
  dedup_append (union, order-preserving — deny_domain has no endpoint-
  rule variant so the endpoint-aware merge_allow_domain doesn't apply).
- network_policy.rs: build_proxy_config() gains a denied_hosts param
  and, per ADR-108 Consequence (b) defense-in-depth, sets strict_filter
  when the *fully assembled* allowlist (resolved policy + extra_hosts)
  is empty but denied_hosts is not. New expand_proxy_deny() mirrors
  expand_proxy_allow() exactly.
- sandbox_prepare.rs / profile_runtime.rs / proxy_runtime.rs /
  launch_runtime.rs: deny_domain threaded through PreparedSandbox,
  PreparedProfile, EffectiveProxySettings, ProxyLaunchOptions and their
  construction/merge logic in parallel to allow_domain; has_proxy_intent()
  and the port-warning pairing mirrored; proxy.strict_filter now ORs
  with (never overwrites) build_proxy_config's own strict-selection so
  the defense-in-depth layer isn't silently discarded.
- main.rs: struct-literal completeness for the new fields.
- nono-profile.schema.json / profile-authoring-guide.md / flags.mdx:
  document deny_domain / --deny-domain.

Signed-off-by: Oscar Mack Jr <oscar.mack.jr@gmail.com>
oscarmackjr-twg added a commit to OscarMackJr/nono that referenced this pull request Aug 15, 2026
…ion passed

Phase 109 complete: 5/5 plans, verification status passed (9/9
must-haves). The verifier re-derived every claim against live code and
live test runs rather than trusting the SUMMARYs - including reading
net_filter.rs directly to confirm deny-before-allow ordering, re-running
the deny_domain (12/12) and no_proxy (9/9) suites, and running cargo
check in ../nono-py itself.

Delivered:
- deny_domain (nolabs-ai#1374) per ADR-108 ADAPT - an additional deny layer
  evaluated before the allowlist, never an allowlist substitute. Guard
  invoked from BOTH command_runtime.rs:155 and launch_runtime.rs:379; a
  guard on one path would be a bypass since dry-run short-circuits.
- Profile-declared no_proxy (nolabs-ai#1415) with all six D-06 overlap validators
  wired at real call sites, rejecting direct, extends-inherited and
  group-expanded overlap. These are the only thing stopping a no_proxy
  entry overlapping allow_domain from silently defeating filtering.
- HTTP_PROXY forward-proxy (nolabs-ai#1335) enforcing the identical check_host
  trust boundary as the CONNECT path, never injecting managed
  credentials on forwarded requests.

Scope corrected during planning: 6fb7ecb (nolabs-ai#1430) and 23d93fc (nolabs-ai#1437)
are N/A - their target files (nono-proxy/src/aws/,
nono-proxy/src/tls_intercept/) do not exist in the fork. Recorded as a
verified finding rather than faked.

Tests: nono-sandbox-proxy 218/0 (192/0 baseline, +26 tests);
nono-sandbox-cli 1411/11 (11 pre-existing environmental, unchanged - they
pass in isolation and this phase never touched those files). Both
cross-target clippy gates GREEN. cargo audit clean.

SC4 vindicated D-09: ../nono-py failed to compile with E0063 missing
fields denied_hosts/no_proxy. Binding struct drift is caught only by
actually building. Fixed and DCO-committed there as e24c1ff.

Two operator amendments proposed, not applied: the Phase 108 ledger's
adopt disposition for the two N/A commits, and REQUIREMENTS.md NET-03's
'are absorbed' wording.

Signed-off-by: Oscar Mack Jr <oscar.mack.jr@gmail.com>
Signed-off-by: oscarmackjr-twg <oscar.mack.jr@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add setting "deny_domain" to complement allow_domain in proxy config

2 participants