mirror of
https://github.com/openai/codex.git
synced 2026-03-03 21:23:18 +00:00
Compare commits
1 Commits
fix/notify
...
leoshimo/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04df7970fc |
@@ -1933,6 +1933,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readAccess": {
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -2037,6 +2040,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess2"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -3097,6 +3108,95 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess2": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess2Type",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess2",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess2Type",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess2",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": "Request from the client to the server.",
|
||||
|
||||
@@ -4303,6 +4303,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -5044,6 +5052,52 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": "Response event from the agent NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.",
|
||||
|
||||
@@ -5343,6 +5343,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -7365,6 +7373,52 @@
|
||||
"samplePaths"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": "Notification sent from the server to the client.",
|
||||
|
||||
@@ -7548,6 +7548,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -9684,6 +9692,52 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"v2": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
@@ -13464,6 +13518,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readAccess": {
|
||||
"$ref": "#/definitions/v2/WorkspaceReadAccess"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -13501,6 +13558,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"$ref": "#/definitions/v2/WorkspaceReadAccess"
|
||||
},
|
||||
"writable_roots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
@@ -16055,6 +16115,49 @@
|
||||
"title": "WindowsWorldWritableWarningNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WriteStatus": {
|
||||
"enum": [
|
||||
"ok",
|
||||
|
||||
@@ -94,6 +94,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -116,6 +124,52 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -4303,6 +4303,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -5044,6 +5052,52 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -4303,6 +4303,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -5044,6 +5052,52 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -255,6 +255,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -324,6 +332,52 @@
|
||||
"byteRange"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -4303,6 +4303,14 @@
|
||||
"description": "When set to `true`, outbound network access is allowed. `false` by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
}
|
||||
],
|
||||
"description": "Controls whether the workspace-write policy has full read access or an explicit read allowlist."
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspace-write"
|
||||
@@ -5044,6 +5052,52 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"description": "Controls read access semantics for `workspace-write` sandbox policies.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Preserve current behavior where all file-system paths are readable.",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"full-read-access"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Restrict reads to an explicit allowlist plus implicitly readable paths.",
|
||||
"properties": {
|
||||
"readable_roots": {
|
||||
"description": "Additional folders that should be readable from inside the sandbox.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restricted-read-access"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -84,6 +84,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readAccess": {
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -106,6 +109,49 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -530,6 +530,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"read_access": {
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
},
|
||||
"writable_roots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
@@ -573,6 +576,49 @@
|
||||
"live"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -571,6 +571,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readAccess": {
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -1538,6 +1541,49 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -571,6 +571,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readAccess": {
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -1538,6 +1541,49 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -571,6 +571,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readAccess": {
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -1538,6 +1541,49 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -176,6 +176,9 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"readAccess": {
|
||||
"$ref": "#/definitions/WorkspaceReadAccess"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
@@ -369,6 +372,49 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WorkspaceReadAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"fullReadAccess"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FullReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"readableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"restrictedReadAccess"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccessType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "RestrictedReadAccessWorkspaceReadAccess",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "./AbsolutePathBuf";
|
||||
import type { NetworkAccess } from "./NetworkAccess";
|
||||
import type { WorkspaceReadAccess } from "./WorkspaceReadAccess";
|
||||
|
||||
/**
|
||||
* Determines execution restrictions for model shell commands.
|
||||
@@ -32,4 +33,9 @@ exclude_tmpdir_env_var: boolean,
|
||||
* When set to `true`, will NOT include the `/tmp` among the default
|
||||
* writable roots on UNIX. Defaults to `false`.
|
||||
*/
|
||||
exclude_slash_tmp: boolean, };
|
||||
exclude_slash_tmp: boolean,
|
||||
/**
|
||||
* Controls whether the workspace-write policy has full read access or
|
||||
* an explicit read allowlist.
|
||||
*/
|
||||
read_access?: WorkspaceReadAccess, };
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "./AbsolutePathBuf";
|
||||
|
||||
/**
|
||||
* Controls read access semantics for `workspace-write` sandbox policies.
|
||||
*/
|
||||
export type WorkspaceReadAccess = { "type": "full-read-access" } | { "type": "restricted-read-access",
|
||||
/**
|
||||
* Additional folders that should be readable from inside the sandbox.
|
||||
*/
|
||||
readable_roots?: Array<AbsolutePathBuf>, };
|
||||
@@ -219,4 +219,5 @@ export type { WebSearchBeginEvent } from "./WebSearchBeginEvent";
|
||||
export type { WebSearchEndEvent } from "./WebSearchEndEvent";
|
||||
export type { WebSearchItem } from "./WebSearchItem";
|
||||
export type { WebSearchMode } from "./WebSearchMode";
|
||||
export type { WorkspaceReadAccess } from "./WorkspaceReadAccess";
|
||||
export * as v2 from "./v2";
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { NetworkAccess } from "./NetworkAccess";
|
||||
import type { WorkspaceReadAccess } from "./WorkspaceReadAccess";
|
||||
|
||||
export type SandboxPolicy = { "type": "dangerFullAccess" } | { "type": "readOnly" } | { "type": "externalSandbox", networkAccess: NetworkAccess, } | { "type": "workspaceWrite", writableRoots: Array<AbsolutePathBuf>, networkAccess: boolean, excludeTmpdirEnvVar: boolean, excludeSlashTmp: boolean, };
|
||||
export type SandboxPolicy = { "type": "dangerFullAccess" } | { "type": "readOnly" } | { "type": "externalSandbox", networkAccess: NetworkAccess, } | { "type": "workspaceWrite", writableRoots: Array<AbsolutePathBuf>, networkAccess: boolean, excludeTmpdirEnvVar: boolean, excludeSlashTmp: boolean, readAccess?: WorkspaceReadAccess, };
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { WorkspaceReadAccess } from "./WorkspaceReadAccess";
|
||||
|
||||
export type SandboxWorkspaceWrite = { writable_roots: Array<string>, network_access: boolean, exclude_tmpdir_env_var: boolean, exclude_slash_tmp: boolean, };
|
||||
export type SandboxWorkspaceWrite = { writable_roots: Array<string>, network_access: boolean, exclude_tmpdir_env_var: boolean, exclude_slash_tmp: boolean, read_access?: WorkspaceReadAccess, };
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
|
||||
export type WorkspaceReadAccess = { "type": "fullReadAccess" } | { "type": "restrictedReadAccess", readableRoots: Array<AbsolutePathBuf>, };
|
||||
@@ -185,4 +185,5 @@ export type { TurnSteerResponse } from "./TurnSteerResponse";
|
||||
export type { UserInput } from "./UserInput";
|
||||
export type { WebSearchAction } from "./WebSearchAction";
|
||||
export type { WindowsWorldWritableWarningNotification } from "./WindowsWorldWritableWarningNotification";
|
||||
export type { WorkspaceReadAccess } from "./WorkspaceReadAccess";
|
||||
export type { WriteStatus } from "./WriteStatus";
|
||||
|
||||
@@ -329,6 +329,8 @@ pub struct SandboxWorkspaceWrite {
|
||||
pub exclude_tmpdir_env_var: bool,
|
||||
#[serde(default)]
|
||||
pub exclude_slash_tmp: bool,
|
||||
#[serde(default, skip_serializing_if = "WorkspaceReadAccess::is_full")]
|
||||
pub read_access: WorkspaceReadAccess,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
@@ -595,6 +597,27 @@ pub enum NetworkAccess {
|
||||
Enabled,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS, Default)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[ts(tag = "type")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub enum WorkspaceReadAccess {
|
||||
#[default]
|
||||
FullReadAccess,
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
RestrictedReadAccess {
|
||||
#[serde(default)]
|
||||
readable_roots: Vec<AbsolutePathBuf>,
|
||||
},
|
||||
}
|
||||
|
||||
impl WorkspaceReadAccess {
|
||||
pub fn is_full(&self) -> bool {
|
||||
matches!(self, WorkspaceReadAccess::FullReadAccess)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[ts(tag = "type")]
|
||||
@@ -619,6 +642,8 @@ pub enum SandboxPolicy {
|
||||
exclude_tmpdir_env_var: bool,
|
||||
#[serde(default)]
|
||||
exclude_slash_tmp: bool,
|
||||
#[serde(default, skip_serializing_if = "WorkspaceReadAccess::is_full")]
|
||||
read_access: WorkspaceReadAccess,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -642,11 +667,22 @@ impl SandboxPolicy {
|
||||
network_access,
|
||||
exclude_tmpdir_env_var,
|
||||
exclude_slash_tmp,
|
||||
read_access,
|
||||
} => codex_protocol::protocol::SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: writable_roots.clone(),
|
||||
network_access: *network_access,
|
||||
exclude_tmpdir_env_var: *exclude_tmpdir_env_var,
|
||||
exclude_slash_tmp: *exclude_slash_tmp,
|
||||
read_access: match read_access {
|
||||
WorkspaceReadAccess::FullReadAccess => {
|
||||
codex_protocol::protocol::WorkspaceReadAccess::FullReadAccess
|
||||
}
|
||||
WorkspaceReadAccess::RestrictedReadAccess { readable_roots } => {
|
||||
codex_protocol::protocol::WorkspaceReadAccess::RestrictedReadAccess {
|
||||
readable_roots: readable_roots.clone(),
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -672,11 +708,20 @@ impl From<codex_protocol::protocol::SandboxPolicy> for SandboxPolicy {
|
||||
network_access,
|
||||
exclude_tmpdir_env_var,
|
||||
exclude_slash_tmp,
|
||||
read_access,
|
||||
} => SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots,
|
||||
network_access,
|
||||
exclude_tmpdir_env_var,
|
||||
exclude_slash_tmp,
|
||||
read_access: match read_access {
|
||||
codex_protocol::protocol::WorkspaceReadAccess::FullReadAccess => {
|
||||
WorkspaceReadAccess::FullReadAccess
|
||||
}
|
||||
codex_protocol::protocol::WorkspaceReadAccess::RestrictedReadAccess {
|
||||
readable_roots,
|
||||
} => WorkspaceReadAccess::RestrictedReadAccess { readable_roots },
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -3143,6 +3188,34 @@ mod tests {
|
||||
assert_eq!(back_to_v2, v2_policy);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sandbox_policy_round_trips_workspace_write_restricted_read_access() {
|
||||
let readable_root = if cfg!(windows) {
|
||||
AbsolutePathBuf::from_absolute_path("C:\\repo\\readable").expect("absolute path")
|
||||
} else {
|
||||
AbsolutePathBuf::from_absolute_path("/repo/readable").expect("absolute path")
|
||||
};
|
||||
let writable_root = if cfg!(windows) {
|
||||
AbsolutePathBuf::from_absolute_path("C:\\repo\\writable").expect("absolute path")
|
||||
} else {
|
||||
AbsolutePathBuf::from_absolute_path("/repo/writable").expect("absolute path")
|
||||
};
|
||||
|
||||
let v2_policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![writable_root],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: WorkspaceReadAccess::RestrictedReadAccess {
|
||||
readable_roots: vec![readable_root],
|
||||
},
|
||||
};
|
||||
|
||||
let core_policy = v2_policy.to_core();
|
||||
let back_to_v2 = SandboxPolicy::from(core_policy);
|
||||
assert_eq!(back_to_v2, v2_policy);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn core_turn_item_into_thread_item_converts_supported_variants() {
|
||||
let user_item = TurnItem::UserMessage(UserMessageItem {
|
||||
|
||||
@@ -288,7 +288,11 @@ You can optionally specify config overrides on the new turn. If specified, these
|
||||
"sandboxPolicy": {
|
||||
"type": "workspaceWrite",
|
||||
"writableRoots": ["/Users/me/project"],
|
||||
"networkAccess": true
|
||||
"networkAccess": true,
|
||||
"readAccess": {
|
||||
"type": "restrictedReadAccess",
|
||||
"readableRoots": ["/Users/me/project", "/Users/me/project/.cache"]
|
||||
}
|
||||
},
|
||||
"model": "gpt-5.1-codex",
|
||||
"effort": "medium",
|
||||
@@ -468,7 +472,7 @@ Run a standalone command (argv vector) in the server’s sandbox without creatin
|
||||
Notes:
|
||||
|
||||
- Empty `command` arrays are rejected.
|
||||
- `sandboxPolicy` accepts the same shape used by `turn/start` (e.g., `dangerFullAccess`, `readOnly`, `workspaceWrite` with flags, `externalSandbox` with `networkAccess` `restricted|enabled`).
|
||||
- `sandboxPolicy` accepts the same shape used by `turn/start` (e.g., `dangerFullAccess`, `readOnly`, `workspaceWrite` with flags including optional `readAccess`, `externalSandbox` with `networkAccess` `restricted|enabled`).
|
||||
- When omitted, `timeoutMs` falls back to the server default.
|
||||
|
||||
## Events
|
||||
|
||||
@@ -447,6 +447,7 @@ async fn test_send_user_turn_updates_sandbox_and_cwd_between_turns() -> Result<(
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
},
|
||||
model: model.clone(),
|
||||
effort: Some(ReasoningEffort::Medium),
|
||||
|
||||
@@ -1102,6 +1102,7 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
}),
|
||||
model: Some("mock-model".to_string()),
|
||||
effort: Some(ReasoningEffort::Medium),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use codex_core::protocol::NetworkAccess;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol::WorkspaceReadAccess;
|
||||
|
||||
pub fn summarize_sandbox_policy(sandbox_policy: &SandboxPolicy) -> String {
|
||||
match sandbox_policy {
|
||||
@@ -17,6 +18,7 @@ pub fn summarize_sandbox_policy(sandbox_policy: &SandboxPolicy) -> String {
|
||||
network_access,
|
||||
exclude_tmpdir_env_var,
|
||||
exclude_slash_tmp,
|
||||
read_access,
|
||||
} => {
|
||||
let mut summary = "workspace-write".to_string();
|
||||
|
||||
@@ -35,6 +37,18 @@ pub fn summarize_sandbox_policy(sandbox_policy: &SandboxPolicy) -> String {
|
||||
);
|
||||
|
||||
summary.push_str(&format!(" [{}]", writable_entries.join(", ")));
|
||||
if let WorkspaceReadAccess::RestrictedReadAccess { readable_roots } = read_access {
|
||||
summary.push_str(" (restricted read access");
|
||||
if !readable_roots.is_empty() {
|
||||
let roots = readable_roots
|
||||
.iter()
|
||||
.map(|path| path.to_string_lossy().to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
summary.push_str(&format!(": {roots}"));
|
||||
}
|
||||
summary.push(')');
|
||||
}
|
||||
if *network_access {
|
||||
summary.push_str(" (network access enabled)");
|
||||
}
|
||||
@@ -74,6 +88,7 @@ mod tests {
|
||||
network_access: true,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
});
|
||||
assert_eq!(
|
||||
summary,
|
||||
@@ -83,4 +98,29 @@ mod tests {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_write_summary_includes_restricted_read_access() {
|
||||
let read_root = if cfg!(windows) {
|
||||
AbsolutePathBuf::try_from("C:\\read").unwrap()
|
||||
} else {
|
||||
AbsolutePathBuf::try_from("/read").unwrap()
|
||||
};
|
||||
let summary = summarize_sandbox_policy(&SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: WorkspaceReadAccess::RestrictedReadAccess {
|
||||
readable_roots: vec![read_root.clone()],
|
||||
},
|
||||
});
|
||||
assert_eq!(
|
||||
summary,
|
||||
format!(
|
||||
"workspace-write [workdir] (restricted read access: {})",
|
||||
read_root.to_string_lossy()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1175,6 +1175,7 @@ impl ConfigToml {
|
||||
network_access: *network_access,
|
||||
exclude_tmpdir_env_var: *exclude_tmpdir_env_var,
|
||||
exclude_slash_tmp: *exclude_slash_tmp,
|
||||
read_access: Default::default(),
|
||||
},
|
||||
None => SandboxPolicy::new_workspace_write_policy(),
|
||||
},
|
||||
@@ -2092,6 +2093,7 @@ exclude_slash_tmp = true
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
},
|
||||
forced_auto_mode_downgraded_on_windows: false,
|
||||
}
|
||||
@@ -2142,6 +2144,7 @@ trust_level = "trusted"
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
},
|
||||
forced_auto_mode_downgraded_on_windows: false,
|
||||
}
|
||||
|
||||
@@ -715,6 +715,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
})
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
@@ -415,6 +415,7 @@ allowed_sandbox_modes = ["read-only"]
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
})
|
||||
.is_err()
|
||||
);
|
||||
|
||||
@@ -198,6 +198,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
assert!(is_write_patch_constrained_to_writable_paths(
|
||||
@@ -219,6 +220,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
assert!(is_write_patch_constrained_to_writable_paths(
|
||||
&add_outside,
|
||||
|
||||
@@ -13,6 +13,8 @@ use crate::spawn::spawn_child_async;
|
||||
|
||||
const MACOS_SEATBELT_BASE_POLICY: &str = include_str!("seatbelt_base_policy.sbpl");
|
||||
const MACOS_SEATBELT_NETWORK_POLICY: &str = include_str!("seatbelt_network_policy.sbpl");
|
||||
const MACOS_SEATBELT_RESTRICTED_READ_BASE_POLICY: &str =
|
||||
include_str!("seatbelt_restricted_read_base_policy.sbpl");
|
||||
|
||||
/// When working with `sandbox-exec`, only consider `sandbox-exec` in `/usr/bin`
|
||||
/// to defend against an attacker trying to inject a malicious version on the
|
||||
@@ -48,6 +50,8 @@ pub(crate) fn create_seatbelt_command_args(
|
||||
sandbox_policy: &SandboxPolicy,
|
||||
sandbox_policy_cwd: &Path,
|
||||
) -> Vec<String> {
|
||||
let has_full_disk_read_access = sandbox_policy.has_full_disk_read_access();
|
||||
|
||||
let (file_write_policy, file_write_dir_params) = {
|
||||
if sandbox_policy.has_full_disk_write_access() {
|
||||
// Allegedly, this is more permissive than `(allow file-write*)`.
|
||||
@@ -105,10 +109,39 @@ pub(crate) fn create_seatbelt_command_args(
|
||||
}
|
||||
};
|
||||
|
||||
let file_read_policy = if sandbox_policy.has_full_disk_read_access() {
|
||||
"; allow read-only file operations\n(allow file-read*)"
|
||||
let (file_read_policy, file_read_dir_params) = if has_full_disk_read_access {
|
||||
(
|
||||
"; allow read-only file operations\n(allow file-read*)".to_string(),
|
||||
Vec::new(),
|
||||
)
|
||||
} else {
|
||||
let readable_roots = sandbox_policy.get_readable_roots_with_cwd(sandbox_policy_cwd);
|
||||
let mut readable_folder_policies: Vec<String> = Vec::new();
|
||||
let mut file_read_params = Vec::new();
|
||||
|
||||
for (index, root) in readable_roots.iter().enumerate() {
|
||||
// Canonicalize to avoid mismatches like /var vs /private/var on macOS.
|
||||
let canonical_root = root
|
||||
.as_path()
|
||||
.canonicalize()
|
||||
.unwrap_or_else(|_| root.to_path_buf());
|
||||
let root_param = format!("READABLE_ROOT_{index}");
|
||||
file_read_params.push((root_param.clone(), canonical_root));
|
||||
readable_folder_policies.push(format!(
|
||||
"(allow file-read* file-map-executable (subpath (param \"{root_param}\")))"
|
||||
));
|
||||
readable_folder_policies.push(format!(
|
||||
"(allow file-read-metadata file-test-existence (path-ancestors (param \"{root_param}\")))"
|
||||
));
|
||||
}
|
||||
|
||||
(readable_folder_policies.join("\n"), file_read_params)
|
||||
};
|
||||
|
||||
let restricted_read_base_policy = if has_full_disk_read_access {
|
||||
""
|
||||
} else {
|
||||
MACOS_SEATBELT_RESTRICTED_READ_BASE_POLICY
|
||||
};
|
||||
|
||||
// TODO(mbolin): apply_patch calls must also honor the SandboxPolicy.
|
||||
@@ -118,11 +151,24 @@ pub(crate) fn create_seatbelt_command_args(
|
||||
""
|
||||
};
|
||||
|
||||
let full_policy = format!(
|
||||
"{MACOS_SEATBELT_BASE_POLICY}\n{file_read_policy}\n{file_write_policy}\n{network_policy}"
|
||||
);
|
||||
let full_policy = [
|
||||
MACOS_SEATBELT_BASE_POLICY,
|
||||
restricted_read_base_policy,
|
||||
file_read_policy.as_str(),
|
||||
file_write_policy.as_str(),
|
||||
network_policy,
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|policy| !policy.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let dir_params = [file_write_dir_params, macos_dir_params()].concat();
|
||||
let dir_params = [
|
||||
file_write_dir_params,
|
||||
file_read_dir_params,
|
||||
macos_dir_params(),
|
||||
]
|
||||
.concat();
|
||||
|
||||
let mut seatbelt_args: Vec<String> = vec!["-p".to_string(), full_policy];
|
||||
let definition_args = dir_params
|
||||
@@ -166,6 +212,7 @@ mod tests {
|
||||
use super::create_seatbelt_command_args;
|
||||
use super::macos_dir_params;
|
||||
use crate::protocol::SandboxPolicy;
|
||||
use crate::protocol::WorkspaceReadAccess;
|
||||
use crate::seatbelt::MACOS_PATH_TO_SEATBELT_EXECUTABLE;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::fs;
|
||||
@@ -210,6 +257,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
// Create the Seatbelt command to wrap a shell command that tries to
|
||||
@@ -240,8 +288,7 @@ mod tests {
|
||||
(allow file-read*)
|
||||
(allow file-write*
|
||||
(require-all (subpath (param "WRITABLE_ROOT_0")) (require-not (subpath (param "WRITABLE_ROOT_0_RO_0"))) (require-not (subpath (param "WRITABLE_ROOT_0_RO_1"))) ) (subpath (param "WRITABLE_ROOT_1")) (subpath (param "WRITABLE_ROOT_2"))
|
||||
)
|
||||
"#,
|
||||
)"#,
|
||||
);
|
||||
|
||||
let mut expected_args = vec![
|
||||
@@ -371,6 +418,48 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_seatbelt_args_with_restricted_read_roots() {
|
||||
let tmp = TempDir::new().expect("tempdir");
|
||||
let cwd = tmp.path().join("cwd");
|
||||
fs::create_dir_all(&cwd).expect("create cwd");
|
||||
let readable_root = tmp.path().join("readable");
|
||||
fs::create_dir_all(&readable_root).expect("create readable root");
|
||||
let readable_root_canonical = readable_root.canonicalize().expect("canonicalize root");
|
||||
|
||||
let policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: WorkspaceReadAccess::RestrictedReadAccess {
|
||||
readable_roots: vec![readable_root.try_into().expect("absolute path")],
|
||||
},
|
||||
};
|
||||
|
||||
let args = create_seatbelt_command_args(vec!["/usr/bin/true".to_string()], &policy, &cwd);
|
||||
let policy_text = args
|
||||
.get(1)
|
||||
.expect("seatbelt policy arg should be present")
|
||||
.to_string();
|
||||
|
||||
assert!(
|
||||
policy_text.contains("(allow file-map-executable"),
|
||||
"restricted read baseline should include file-map-executable rules"
|
||||
);
|
||||
assert!(
|
||||
policy_text.contains("(param \"READABLE_ROOT_0\")"),
|
||||
"restricted read policy should include parameterized readable roots"
|
||||
);
|
||||
assert!(
|
||||
args.contains(&format!(
|
||||
"-DREADABLE_ROOT_0={}",
|
||||
readable_root_canonical.to_string_lossy()
|
||||
)),
|
||||
"expected readable root parameter in args: {args:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_seatbelt_args_with_read_only_git_pointer_file() {
|
||||
let tmp = TempDir::new().expect("tempdir");
|
||||
@@ -394,6 +483,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let shell_command: Vec<String> = [
|
||||
@@ -477,6 +567,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let shell_command: Vec<String> = [
|
||||
@@ -518,8 +609,7 @@ mod tests {
|
||||
(allow file-read*)
|
||||
(allow file-write*
|
||||
(require-all (subpath (param "WRITABLE_ROOT_0")) (require-not (subpath (param "WRITABLE_ROOT_0_RO_0"))) (require-not (subpath (param "WRITABLE_ROOT_0_RO_1"))) ) (subpath (param "WRITABLE_ROOT_1")){tempdir_policy_entry}
|
||||
)
|
||||
"#,
|
||||
)"#,
|
||||
);
|
||||
|
||||
let mut expected_args = vec![
|
||||
|
||||
49
codex-rs/core/src/seatbelt_restricted_read_base_policy.sbpl
Normal file
49
codex-rs/core/src/seatbelt_restricted_read_base_policy.sbpl
Normal file
@@ -0,0 +1,49 @@
|
||||
; baseline read access for restricted-read workspace-write policies
|
||||
; keeps the runtime and dynamic loader functional without globally allowing
|
||||
; file-read* on all paths.
|
||||
|
||||
; shell/runtime binaries
|
||||
(allow file-read-data file-read-metadata
|
||||
(subpath "/bin")
|
||||
(subpath "/sbin")
|
||||
(subpath "/usr/bin")
|
||||
(subpath "/usr/sbin")
|
||||
(subpath "/usr/libexec"))
|
||||
|
||||
; standard shell configuration loaded by /bin/zsh
|
||||
(allow file-read-data file-read-metadata
|
||||
(literal "/etc/zshenv")
|
||||
(literal "/etc/zprofile")
|
||||
(literal "/etc/zlogin"))
|
||||
|
||||
; dynamic loader + frameworks
|
||||
(allow file-read* file-test-existence
|
||||
(subpath "/Library/Apple")
|
||||
(subpath "/System")
|
||||
(subpath "/usr/lib")
|
||||
(subpath "/usr/share"))
|
||||
|
||||
(allow file-map-executable
|
||||
(subpath "/Library/Apple/System/Library/Frameworks")
|
||||
(subpath "/Library/Apple/System/Library/PrivateFrameworks")
|
||||
(subpath "/Library/Apple/usr/lib")
|
||||
(subpath "/System/Library/Frameworks")
|
||||
(subpath "/System/Library/PrivateFrameworks")
|
||||
(subpath "/System/Library/SubFrameworks")
|
||||
(subpath "/usr/lib"))
|
||||
|
||||
; allow path traversal for common symlinked roots
|
||||
(allow file-read-metadata file-test-existence
|
||||
(literal "/")
|
||||
(literal "/etc")
|
||||
(literal "/tmp")
|
||||
(literal "/var")
|
||||
(literal "/private/etc/localtime")
|
||||
(path-ancestors "/System/Volumes/Data/private"))
|
||||
|
||||
; resolver / service metadata commonly read at startup
|
||||
(allow file-read* file-test-existence
|
||||
(literal "/private/etc/master.passwd")
|
||||
(literal "/private/etc/passwd")
|
||||
(literal "/private/etc/protocols")
|
||||
(literal "/private/etc/services"))
|
||||
@@ -581,6 +581,7 @@ async fn apply_patch_cli_rejects_path_traversal_outside_workspace(
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
harness
|
||||
.submit_with_policy(
|
||||
@@ -637,6 +638,7 @@ async fn apply_patch_cli_rejects_move_path_traversal_outside_workspace(
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
harness
|
||||
.submit_with_policy("attempt move traversal via apply_patch", sandbox_policy)
|
||||
|
||||
@@ -631,6 +631,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
|
||||
network_access,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
vec![
|
||||
@@ -1576,6 +1577,7 @@ async fn approving_apply_patch_for_session_skips_future_prompts_for_same_file()
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
let sandbox_policy_for_config = sandbox_policy.clone();
|
||||
|
||||
|
||||
@@ -460,6 +460,7 @@ async fn permissions_message_includes_writable_roots() -> Result<()> {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
let sandbox_policy_for_config = sandbox_policy.clone();
|
||||
|
||||
|
||||
@@ -377,6 +377,7 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an
|
||||
network_access: true,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
codex
|
||||
.submit(Op::OverrideTurnContext {
|
||||
@@ -618,6 +619,7 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
|
||||
network_access: true,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
|
||||
@@ -80,6 +80,7 @@ async fn if_parent_of_repo_is_writable_then_dot_git_folder_is_writable() {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
test_scenario
|
||||
@@ -106,6 +107,7 @@ async fn if_git_repo_is_writable_root_then_dot_git_folder_is_read_only() {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
test_scenario
|
||||
|
||||
@@ -116,6 +116,7 @@ where
|
||||
// strict about what is writable.
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
},
|
||||
codex_linux_sandbox_exe,
|
||||
sandbox_cwd: writable_folder.as_ref().to_path_buf(),
|
||||
|
||||
@@ -135,6 +135,7 @@ async fn python_multiprocessing_lock_works_under_sandbox() {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let python_code = r#"import multiprocessing
|
||||
@@ -248,6 +249,7 @@ async fn sandbox_distinguishes_command_and_policy_cwds() {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
// Attempt to write inside the command cwd, which is outside of the sandbox policy cwd.
|
||||
|
||||
@@ -92,6 +92,7 @@ async fn run_cmd_result_with_writable_roots(
|
||||
// writing to in the sandbox.
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
let sandbox_program = env!("CARGO_BIN_EXE_codex-linux-sandbox");
|
||||
let codex_linux_sandbox_exe = Some(PathBuf::from(sandbox_program));
|
||||
|
||||
@@ -1216,6 +1216,7 @@ mod tests {
|
||||
network_access: true,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let instructions = DeveloperInstructions::from_policy(
|
||||
|
||||
@@ -376,6 +376,29 @@ impl NetworkAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/// Controls read access semantics for `workspace-write` sandbox policies.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Display, Default, JsonSchema, TS)]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
#[serde(tag = "type", rename_all = "kebab-case")]
|
||||
pub enum WorkspaceReadAccess {
|
||||
/// Preserve current behavior where all file-system paths are readable.
|
||||
#[default]
|
||||
FullReadAccess,
|
||||
|
||||
/// Restrict reads to an explicit allowlist plus implicitly readable paths.
|
||||
RestrictedReadAccess {
|
||||
/// Additional folders that should be readable from inside the sandbox.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
readable_roots: Vec<AbsolutePathBuf>,
|
||||
},
|
||||
}
|
||||
|
||||
impl WorkspaceReadAccess {
|
||||
pub fn is_full(&self) -> bool {
|
||||
matches!(self, WorkspaceReadAccess::FullReadAccess)
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines execution restrictions for model shell commands.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Display, JsonSchema, TS)]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
@@ -422,6 +445,11 @@ pub enum SandboxPolicy {
|
||||
/// writable roots on UNIX. Defaults to `false`.
|
||||
#[serde(default)]
|
||||
exclude_slash_tmp: bool,
|
||||
|
||||
/// Controls whether the workspace-write policy has full read access or
|
||||
/// an explicit read allowlist.
|
||||
#[serde(default, skip_serializing_if = "WorkspaceReadAccess::is_full")]
|
||||
read_access: WorkspaceReadAccess,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -479,12 +507,48 @@ impl SandboxPolicy {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: WorkspaceReadAccess::FullReadAccess,
|
||||
}
|
||||
}
|
||||
|
||||
/// Always returns `true`; restricting read access is not supported.
|
||||
pub fn has_full_disk_read_access(&self) -> bool {
|
||||
true
|
||||
match self {
|
||||
SandboxPolicy::DangerFullAccess => true,
|
||||
SandboxPolicy::ExternalSandbox { .. } => true,
|
||||
SandboxPolicy::ReadOnly => true,
|
||||
SandboxPolicy::WorkspaceWrite { read_access, .. } => {
|
||||
matches!(read_access, WorkspaceReadAccess::FullReadAccess)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns readable roots tailored to cwd when read access is restricted.
|
||||
/// Returns an empty list when the policy has full disk read access.
|
||||
pub fn get_readable_roots_with_cwd(&self, cwd: &Path) -> Vec<AbsolutePathBuf> {
|
||||
match self {
|
||||
SandboxPolicy::DangerFullAccess => Vec::new(),
|
||||
SandboxPolicy::ExternalSandbox { .. } => Vec::new(),
|
||||
SandboxPolicy::ReadOnly => Vec::new(),
|
||||
SandboxPolicy::WorkspaceWrite { read_access, .. } => match read_access {
|
||||
WorkspaceReadAccess::FullReadAccess => Vec::new(),
|
||||
WorkspaceReadAccess::RestrictedReadAccess { readable_roots } => {
|
||||
let mut roots = readable_roots.clone();
|
||||
roots.extend(
|
||||
self.get_writable_roots_with_cwd(cwd)
|
||||
.into_iter()
|
||||
.map(|root| root.root),
|
||||
);
|
||||
|
||||
let mut deduped = Vec::new();
|
||||
for root in roots {
|
||||
if !deduped.iter().any(|existing| existing == &root) {
|
||||
deduped.push(root);
|
||||
}
|
||||
}
|
||||
deduped
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_full_disk_write_access(&self) -> bool {
|
||||
@@ -517,6 +581,7 @@ impl SandboxPolicy {
|
||||
writable_roots,
|
||||
exclude_tmpdir_env_var,
|
||||
exclude_slash_tmp,
|
||||
read_access: _,
|
||||
network_access: _,
|
||||
} => {
|
||||
// Start from explicitly configured writable roots.
|
||||
@@ -2482,6 +2547,7 @@ mod tests {
|
||||
use crate::items::UserMessageItem;
|
||||
use crate::items::WebSearchItem;
|
||||
use anyhow::Result;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use tempfile::NamedTempFile;
|
||||
@@ -2501,6 +2567,52 @@ mod tests {
|
||||
assert!(enabled.has_full_network_access());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_write_restricted_read_reports_not_full_read_access() {
|
||||
let policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: WorkspaceReadAccess::RestrictedReadAccess {
|
||||
readable_roots: vec![],
|
||||
},
|
||||
};
|
||||
|
||||
assert!(!policy.has_full_disk_read_access());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_write_restricted_readable_roots_include_writable_roots() -> Result<()> {
|
||||
let (cwd, writable_root, readable_root) = if cfg!(windows) {
|
||||
(
|
||||
AbsolutePathBuf::from_absolute_path("C:\\repo\\cwd")?,
|
||||
AbsolutePathBuf::from_absolute_path("C:\\repo\\writable")?,
|
||||
AbsolutePathBuf::from_absolute_path("C:\\repo\\readable")?,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
AbsolutePathBuf::from_absolute_path("/repo/cwd")?,
|
||||
AbsolutePathBuf::from_absolute_path("/repo/writable")?,
|
||||
AbsolutePathBuf::from_absolute_path("/repo/readable")?,
|
||||
)
|
||||
};
|
||||
|
||||
let policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![writable_root.clone()],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
read_access: WorkspaceReadAccess::RestrictedReadAccess {
|
||||
readable_roots: vec![readable_root.clone()],
|
||||
},
|
||||
};
|
||||
|
||||
let readable_roots = policy.get_readable_roots_with_cwd(cwd.as_path());
|
||||
assert_eq!(readable_roots, vec![readable_root, writable_root, cwd]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn item_started_event_from_web_search_emits_begin_event() {
|
||||
let event = ItemStartedEvent {
|
||||
|
||||
@@ -3490,6 +3490,7 @@ async fn preset_matching_ignores_extra_writable_roots() {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
assert!(
|
||||
|
||||
@@ -103,6 +103,7 @@ async fn status_snapshot_includes_reasoning_details() {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
})
|
||||
.expect("set sandbox policy");
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let paths = compute_allow_paths(&policy, &command_cwd, &command_cwd, &HashMap::new());
|
||||
@@ -137,6 +138,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
let mut env_map = HashMap::new();
|
||||
env_map.insert("TEMP".into(), temp_dir.to_string_lossy().to_string());
|
||||
@@ -164,6 +166,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let paths = compute_allow_paths(&policy, &command_cwd, &command_cwd, &HashMap::new());
|
||||
@@ -191,6 +194,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let paths = compute_allow_paths(&policy, &command_cwd, &command_cwd, &HashMap::new());
|
||||
@@ -216,6 +220,7 @@ mod tests {
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
};
|
||||
|
||||
let paths = compute_allow_paths(&policy, &command_cwd, &command_cwd, &HashMap::new());
|
||||
|
||||
@@ -472,6 +472,7 @@ mod windows_impl {
|
||||
network_access,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -513,6 +513,7 @@ mod windows_impl {
|
||||
network_access,
|
||||
exclude_tmpdir_env_var: false,
|
||||
exclude_slash_tmp: false,
|
||||
read_access: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
351
skyshield_base_policy.txt
Normal file
351
skyshield_base_policy.txt
Normal file
@@ -0,0 +1,351 @@
|
||||
private func baseSandboxPolicy(
|
||||
temporaryDirectory: URL,
|
||||
allowedReadFolders: [URL],
|
||||
allowedWriteFolders: [URL],
|
||||
sandboxPolicyOptions: TinyskySandboxPolicyOptions?,
|
||||
) -> String {
|
||||
// Sandbox policies require fully-resolved paths
|
||||
var temporaryPath = temporaryDirectory.resolvingSymlinksInPath().path
|
||||
|
||||
// Per documentation, URL.resolveSymlinksInPath() strips /private from /var paths; we re-add it
|
||||
if temporaryPath.hasPrefix("/var") {
|
||||
temporaryPath = "/private" + temporaryDirectory.path
|
||||
}
|
||||
|
||||
let allowedReadOnlyFolderRules = allowedReadOnlyFolderRules(for: allowedReadFolders)
|
||||
let allowedWriteOnlyFolderRules = allowedWriteFolderRules(for: allowedWriteFolders)
|
||||
let sandboxPolicyOptionsRules = rules(for: sandboxPolicyOptions) ?? ""
|
||||
|
||||
return """
|
||||
(version 1)
|
||||
|
||||
; inspired by Chrome's sandbox policy:
|
||||
; https://source.chromium.org/chromium/chromium/src/+/main:sandbox/policy/mac/common.sb;l=273-319;drc=7b3962fe2e5fc9e2ee58000dc8fbf3429d84d3bd
|
||||
; https://source.chromium.org/chromium/chromium/src/+/main:sandbox/policy/mac/renderer.sb;l=64;drc=7b3962fe2e5fc9e2ee58000dc8fbf3429d84d3bd
|
||||
|
||||
; start with closed-by-default
|
||||
(deny default)
|
||||
|
||||
; Read access to standard system paths
|
||||
(allow file-read* file-test-existence
|
||||
(subpath "/Library/Apple")
|
||||
(subpath "/Library/Filesystems/NetFSPlugins")
|
||||
(subpath "/Library/Preferences/Logging")
|
||||
(subpath "/System")
|
||||
(literal "/private/var/db/DarwinDirectory/local/recordStore.data")
|
||||
(subpath "/private/var/db/timezone")
|
||||
(subpath "/usr/lib")
|
||||
(subpath "/usr/share"))
|
||||
|
||||
; Map system frameworks + dylibs
|
||||
(allow file-map-executable
|
||||
(subpath "/Library/Apple/System/Library/Frameworks")
|
||||
(subpath "/Library/Apple/System/Library/PrivateFrameworks")
|
||||
(subpath "/Library/Apple/usr/lib")
|
||||
(subpath "/System/Library/Extensions")
|
||||
(subpath "/System/Library/Frameworks")
|
||||
(subpath "/System/Library/PrivateFrameworks")
|
||||
(subpath "/System/Library/SubFrameworks")
|
||||
(subpath "/System/iOSSupport/System/Library/Frameworks")
|
||||
(subpath "/System/iOSSupport/System/Library/PrivateFrameworks")
|
||||
(subpath "/System/iOSSupport/System/Library/SubFrameworks")
|
||||
(subpath "/usr/lib"))
|
||||
|
||||
; Allow guarded vnodes.
|
||||
(allow system-mac-syscall (mac-policy-name "vnguard"))
|
||||
|
||||
; Determine whether a container is expected.
|
||||
(allow system-mac-syscall
|
||||
(require-all
|
||||
(mac-policy-name "Sandbox")
|
||||
(mac-syscall-number 67)))
|
||||
|
||||
; Allow resolution of standard system symlinks.
|
||||
(allow file-read-metadata file-test-existence
|
||||
(literal "/etc")
|
||||
(literal "/tmp")
|
||||
(literal "/var")
|
||||
(literal "/private/etc/localtime"))
|
||||
|
||||
; Allow stat'ing of path components of firmlink targets.
|
||||
(allow file-read-metadata file-test-existence
|
||||
(path-ancestors "/System/Volumes/Data/private"))
|
||||
|
||||
; Allow processes to get their current working directory.
|
||||
(allow file-read* file-test-existence
|
||||
(literal "/"))
|
||||
|
||||
; Allow FSIOC_CAS_BSDFLAGS as an alternate chflags(2).
|
||||
(allow system-fsctl (fsctl-command FSIOC_CAS_BSDFLAGS))
|
||||
|
||||
; Allow access to standard special files.
|
||||
(allow file-read* file-test-existence
|
||||
(literal "/dev/autofs_nowait")
|
||||
(literal "/dev/random")
|
||||
(literal "/dev/urandom")
|
||||
(literal "/private/etc/master.passwd")
|
||||
(literal "/private/etc/passwd")
|
||||
(literal "/private/etc/protocols")
|
||||
(literal "/private/etc/services"))
|
||||
|
||||
(allow file-read* file-test-existence file-write-data
|
||||
(literal "/dev/null")
|
||||
(literal "/dev/zero"))
|
||||
|
||||
; Allow read/write access to the file descriptors.
|
||||
(allow file-read-data file-test-existence file-write-data
|
||||
(subpath "/dev/fd"))
|
||||
|
||||
(allow file-read* file-test-existence file-write-data file-ioctl
|
||||
(literal "/dev/dtracehelper"))
|
||||
|
||||
; Regulatory domain support
|
||||
(allow file-read*
|
||||
(literal "/private/var/db/eligibilityd/eligibility.plist"))
|
||||
|
||||
; Allow IPC to standard system agents.
|
||||
(allow network-outbound
|
||||
(literal "/private/var/run/syslog"))
|
||||
|
||||
(allow ipc-posix-shm-read*
|
||||
(ipc-posix-name "apple.shm.notification_center")
|
||||
(ipc-posix-name-prefix "apple.cfprefs."))
|
||||
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.analyticsd")
|
||||
(global-name "com.apple.analyticsd.messagetracer")
|
||||
(global-name "com.apple.appsleep")
|
||||
(global-name "com.apple.bsd.dirhelper")
|
||||
(global-name "com.apple.cfprefsd.agent")
|
||||
(global-name "com.apple.cfprefsd.daemon")
|
||||
(global-name "com.apple.diagnosticd")
|
||||
(global-name "com.apple.dt.automationmode.reader")
|
||||
(global-name "com.apple.espd")
|
||||
(global-name "com.apple.logd")
|
||||
(global-name "com.apple.logd.events")
|
||||
(global-name "com.apple.runningboard")
|
||||
(global-name "com.apple.secinitd")
|
||||
(global-name "com.apple.system.DirectoryService.libinfo_v1")
|
||||
(global-name "com.apple.system.logger")
|
||||
(global-name "com.apple.system.notification_center")
|
||||
(global-name "com.apple.system.opendirectoryd.libinfo")
|
||||
(global-name "com.apple.system.opendirectoryd.membership")
|
||||
(global-name "com.apple.trustd")
|
||||
(global-name "com.apple.trustd.agent")
|
||||
(global-name "com.apple.xpc.activity.unmanaged")
|
||||
(local-name "com.apple.cfprefsd.agent"))
|
||||
|
||||
; Allow mostly harmless operations.
|
||||
(allow sysctl-read)
|
||||
(allow sysctl-write
|
||||
(sysctl-name "kern.grade_cputype"
|
||||
"kern.wq_limit_cooperative_threads"))
|
||||
|
||||
; (system-graphics)
|
||||
(define (system-graphics)
|
||||
(allow user-preference-read
|
||||
(preference-domain "com.apple.gpu")
|
||||
(preference-domain "com.apple.opengl")
|
||||
(preference-domain "com.nvidia.OpenGL"))
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.gpumemd.source"))
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.lsd.mapdb"))
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.CARenderServer")
|
||||
(global-name "com.apple.CoreDisplay.master")
|
||||
(global-name "com.apple.CoreDisplay.Notification"))
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.cvmsServ"))
|
||||
(allow file-read*
|
||||
(subpath "/private/var/db/CVMS"))
|
||||
(allow iokit-open-service
|
||||
(iokit-registry-entry-class "IOAccelerator"
|
||||
"IOSurfaceRoot"))
|
||||
(allow iokit-open-user-client
|
||||
(iokit-connection "IOAccelerator")
|
||||
(iokit-user-client-class "IOAccelerationUserClient"
|
||||
"IOSurfaceAcceleratorClient"
|
||||
"IOSurfaceRootUserClient"
|
||||
"IOSurfaceSendRight"))
|
||||
(allow iokit-open-service
|
||||
(iokit-registry-entry-class "IOFramebuffer"))
|
||||
(allow iokit-open-user-client
|
||||
(iokit-user-client-class "IOFramebufferSharedUserClient"))
|
||||
(allow iokit-open-service
|
||||
(iokit-connection "AppleGraphicsDeviceControl"))
|
||||
(allow iokit-open-user-client
|
||||
(iokit-user-client-class "AppleIntelMEUserClient"
|
||||
"AppleSNBFBUserClient"))
|
||||
(allow iokit-open-service
|
||||
(iokit-registry-entry-class "AGPM"
|
||||
"AppleGraphicsControl"
|
||||
"AppleGraphicsPolicy"))
|
||||
(allow iokit-open-user-client
|
||||
(iokit-user-client-class "AGPMClient"
|
||||
"AppleGraphicsControlClient"
|
||||
"AppleGraphicsPolicyClient"))
|
||||
(allow iokit-open-user-client
|
||||
(iokit-user-client-class "AppleMGPUPowerControlClient"))
|
||||
(allow file-read* file-test-existence
|
||||
(subpath "/Library/GPUBundles"))
|
||||
(allow iokit-set-properties
|
||||
(require-all
|
||||
(iokit-connection "IODisplay")
|
||||
(require-any
|
||||
(iokit-property "brightness"
|
||||
"linear-brightness"
|
||||
"commit"
|
||||
"rgcs"
|
||||
"ggcs"
|
||||
"bgcs")))))
|
||||
|
||||
; OOPJIT support
|
||||
(define (oopjit-runner)
|
||||
(allow file-read* file-map-executable file-write-unlink
|
||||
(extension "com.apple.sandbox.oopjit")))
|
||||
|
||||
; child processes inherit the policy of their parent
|
||||
(allow process-exec)
|
||||
(allow process-fork)
|
||||
(allow signal (target same-sandbox))
|
||||
|
||||
; Allow cf prefs to work.
|
||||
(allow user-preference-read)
|
||||
|
||||
; process-info
|
||||
(allow process-info* (target same-sandbox))
|
||||
|
||||
(allow file-write-data
|
||||
(require-all
|
||||
(path "/dev/null")
|
||||
(vnode-type CHARACTER-DEVICE)))
|
||||
|
||||
; --- Allow reading the minimum system runtime so exec works ---
|
||||
(allow file-read-data (subpath "/bin"))
|
||||
(allow file-read-metadata (subpath "/bin"))
|
||||
(allow file-read-data (subpath "/sbin"))
|
||||
(allow file-read-metadata (subpath "/sbin"))
|
||||
(allow file-read-data (subpath "/usr/bin"))
|
||||
(allow file-read-metadata (subpath "/usr/bin"))
|
||||
(allow file-read-data (subpath "/usr/sbin"))
|
||||
(allow file-read-metadata (subpath "/usr/sbin"))
|
||||
(allow file-read-data (subpath "/usr/libexec"))
|
||||
(allow file-read-metadata (subpath "/usr/libexec"))
|
||||
|
||||
; zsh system config
|
||||
(allow file-read-data (literal "/etc/zshenv"))
|
||||
(allow file-read-metadata (literal "/etc/zshenv"))
|
||||
(allow file-read-data (literal "/etc/zprofile"))
|
||||
(allow file-read-metadata (literal "/etc/zprofile"))
|
||||
(allow file-read-data (literal "/etc/zlogin"))
|
||||
(allow file-read-metadata (literal "/etc/zlogin"))
|
||||
|
||||
(allow file-read* (subpath "/Library/Preferences"))
|
||||
(allow file-read* (subpath "/var/db"))
|
||||
(allow file-read* (subpath "/private/var/db"))
|
||||
|
||||
; dyld cache metadata outside /System
|
||||
(allow file-read* (subpath "/private/var/db/dyld"))
|
||||
(allow file-read* (subpath "/var/db/dyld"))
|
||||
|
||||
; common 3rd-party dylib / framework locations
|
||||
; Homebrew
|
||||
(allow file-read* (subpath "/opt/homebrew/lib"))
|
||||
(allow file-read* (subpath "/usr/local/lib"))
|
||||
|
||||
; App bundles
|
||||
(allow file-read* (subpath "/Applications"))
|
||||
|
||||
; terminal basics
|
||||
(allow file-read* (regex "^/dev/fd/(0|1|2)$"))
|
||||
(allow file-write* (regex "^/dev/fd/(1|2)$"))
|
||||
(allow file-read* file-write* (literal "/dev/null"))
|
||||
(allow file-read* file-write* (literal "/dev/tty"))
|
||||
(allow file-read-metadata (literal "/dev"))
|
||||
(allow file-read-metadata (regex "^/dev/.*$"))
|
||||
(allow file-read-metadata (literal "/dev/stdin"))
|
||||
(allow file-read-metadata (literal "/dev/stdout"))
|
||||
(allow file-read-metadata (literal "/dev/stderr"))
|
||||
(allow file-read-metadata (regex "^/dev/tty[^/]*$"))
|
||||
(allow file-read-metadata (regex "^/dev/pty[^/]*$"))
|
||||
(allow file-read* file-write* (regex "^/dev/ttys[0-9]+$"))
|
||||
(allow file-read* file-write* (literal "/dev/ptmx"))
|
||||
|
||||
; scratch space (so tools can create temp files)
|
||||
(allow file-read* file-write* (subpath "/tmp"))
|
||||
(allow file-read* file-write* (subpath "/private/tmp"))
|
||||
(allow file-read* file-write* (subpath "/var/tmp"))
|
||||
(allow file-read* file-write* (subpath "/private/var/tmp"))
|
||||
|
||||
(allow file-read* (subpath "/etc"))
|
||||
(allow file-read* (subpath "/private/etc"))
|
||||
|
||||
; Some processes read /var metadata during startup
|
||||
(allow file-read-metadata (subpath "/var"))
|
||||
(allow file-read-metadata (subpath "/private/var"))
|
||||
|
||||
; IOKit
|
||||
(allow iokit-open
|
||||
(iokit-registry-entry-class "RootDomainUserClient")
|
||||
)
|
||||
|
||||
; needed to look up user info, see https://crbug.com/792228
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.system.opendirectoryd.libinfo")
|
||||
)
|
||||
|
||||
; Unified logging (os_log) needs logd
|
||||
(allow mach-lookup
|
||||
(global-name-prefix "com.apple.logd")
|
||||
(global-name "com.apple.system.logger")
|
||||
)
|
||||
|
||||
; Diagnostics daemon (sometimes queried on startup)
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.diagnosticd")
|
||||
(global-name-prefix "com.apple.diagnosticd")
|
||||
)
|
||||
|
||||
; Needed for python multiprocessing on MacOS for the SemLock
|
||||
(allow ipc-posix-sem)
|
||||
|
||||
(allow mach-lookup
|
||||
(global-name "com.apple.PowerManagement.control")
|
||||
)
|
||||
|
||||
; allow openpty()
|
||||
(allow pseudo-tty)
|
||||
(allow file-read* file-write* file-ioctl (literal "/dev/ptmx"))
|
||||
(allow file-read* file-write*
|
||||
(require-all
|
||||
(regex #"^/dev/ttys[0-9]+")))
|
||||
; PTYs created before entering seatbelt may lack the extension; allow ioctl
|
||||
; on those slave ttys so interactive shells detect a TTY and remain functional.
|
||||
(allow file-ioctl (regex #"^/dev/ttys[0-9]+"))
|
||||
|
||||
(allow mach-lookup (global-name "com.apple.audio.audiohald"))
|
||||
(allow mach-lookup (global-name "com.apple.audio.AudioComponentRegistrar"))
|
||||
(allow file-read-data (subpath "/etc"))
|
||||
(allow file-read-metadata (subpath "/etc"))
|
||||
(allow file-read-data (subpath "/usr"))
|
||||
(allow file-read-metadata (subpath "/usr"))
|
||||
|
||||
; allow metadata traversal for firmlink parents
|
||||
(allow file-read-metadata (literal "/System/Volumes") (vnode-type DIRECTORY))
|
||||
(allow file-read-metadata (literal "/System/Volumes/Data") (vnode-type DIRECTORY))
|
||||
(allow file-read-metadata (literal "/System/Volumes/Data/Users") (vnode-type DIRECTORY))
|
||||
|
||||
\(allowedReadOnlyFolderRules)
|
||||
\(allowedWriteOnlyFolderRules)
|
||||
\(sandboxPolicyOptionsRules)
|
||||
(allow file-read* file-write* (subpath "\(temporaryPath)"))
|
||||
|
||||
(allow mach-lookup (global-name "\(SkyShieldCommandProxyIPCServer.messagePortName)"))
|
||||
(allow mach-lookup (global-name "\(SkyShieldSandboxExtensionIPCServer.messagePortName)"))
|
||||
|
||||
; Allow app-sandbox file extensions to grant access
|
||||
(allow file-read* (extension "com.apple.app-sandbox.read"))
|
||||
(allow file-read* file-write* (extension "com.apple.app-sandbox.read-write"))
|
||||
"""
|
||||
}
|
||||
Reference in New Issue
Block a user