Enforce environment-specific command policies (#38942)

## What changed

- Add an optional restrictive execution policy to `EnvironmentConfig` and merge it over the active command policy for shell execution and approval decisions.
- Reject environment policies that contain allow rules, so environment configuration can only tighten command access.
- Include the environment policy fingerprint in cached approval keys so policy changes require fresh session approvals.

## Testing

- Cover restrictions overriding saved prefix approvals, policy changes invalidating session approvals, and environment overlays remaining effective when model-specific prefix filtering is active.

GitOrigin-RevId: e94f877549ed5e0f577b8cb52f3c1872c58f029d
This commit is contained in:
sayan-oai authored and copyberry committed 2026-08-17 04:37:50 +00:00
1 parent 89e297729e
commit e38290846c
27 files changed
+364 -17

No files matched your search

+12 -12
View File
@@ -41,11 +41,22 @@ impl RequirementsExecPolicy {
pub fn new(policy: Policy) -> Self {
Self { policy }
}
pub fn fingerprint(&self) -> Vec<String> {
let mut entries = Vec::new();
for (program, rules) in self.policy.rules().iter_all() {
for rule in rules {
entries.push(format!("{program}:{rule:?}"));
}
}
entries.sort();
entries
}
}
impl PartialEq for RequirementsExecPolicy {
fn eq(&self, other: &Self) -> bool {
policy_fingerprint(&self.policy) == policy_fingerprint(&other.policy)
self.fingerprint() == other.fingerprint()
}
}
@@ -57,17 +68,6 @@ impl AsRef<Policy> for RequirementsExecPolicy {
}
}
fn policy_fingerprint(policy: &Policy) -> Vec<String> {
let mut entries = Vec::new();
for (program, rules) in policy.rules().iter_all() {
for rule in rules {
entries.push(format!("{program}:{rule:?}"));
}
}
entries.sort();
entries
}
impl Policy {
pub fn new(rules_by_program: MultiMap<String, RuleRef>) -> Self {
Self::from_parts(rules_by_program, Vec::new(), HashMap::new())