Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions agents/langchain-deepagents-code/dcode-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ run_dcode() {
# TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN) are allowed only when the value
# matches the platform-specific token shape AND does not embed a
# non-platform canonical secret prefix.
# * Managed observability endpoint values are allowed only for the
# credential-free local OpenShell OTLP collector and only from the
# runtime environment. Mutable .env files still fail closed.
# * The env-file parser strips a leading `export ` keyword (mirroring
# python-dotenv) and rejects values containing dotenv expansion ($VAR,
# ${VAR}), command substitution ($(...) or backticks), because upstream
Expand Down Expand Up @@ -263,6 +266,23 @@ is_managed_token_value_for_name() {
return 1
}

is_managed_observability_endpoint_value() {
local name="$1"
local value="${2%/}"
case "$name" in
OTEL_EXPORTER_OTLP_ENDPOINT)
[ "$value" = "http://host.openshell.internal:4318" ] \
|| [ "$value" = "http://host.openshell.internal:4318/v1/traces" ]
;;
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)
[ "$value" = "http://host.openshell.internal:4318/v1/traces" ]
;;
*)
return 1
;;
esac
}

trim_whitespace() {
local s="$1"
s="${s#"${s%%[![:space:]]*}"}"
Expand Down Expand Up @@ -442,6 +462,9 @@ assert_no_secret_runtime_env() {
if is_managed_token_value_for_name "$name" "$value"; then
continue
fi
if is_managed_observability_endpoint_value "$name" "$value"; then
continue
fi
if is_secret_shaped_value "$value"; then
refuse_secret_env "runtime environment variable" "$name"
fi
Expand Down
12 changes: 12 additions & 0 deletions agents/langchain-deepagents-code/managed-dcode-runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@
r"[^\t\n\v\f\r \u00a0\u1680\u2000-\u200a\u2028\u2029"
r"\u202f\u205f\u3000\ufeff'\"]"
)
_MANAGED_OBSERVABILITY_ENDPOINTS = {
"OTEL_EXPORTER_OTLP_ENDPOINT": {
"http://host.openshell.internal:4318",
"http://host.openshell.internal:4318/v1/traces",
},
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": {
"http://host.openshell.internal:4318/v1/traces",
},
}
_OPENSHELL_ENV_PLACEHOLDER_PREFIX = "openshell:resolve:env:"
_UPSTREAM_PROVIDER_ENV = "NEMOCLAW_UPSTREAM_PROVIDER"
_MANAGED_ADAPTER_PROVIDER = "openai"
Expand Down Expand Up @@ -200,6 +209,9 @@ def _is_managed_value(name: str, value: str) -> bool:
return value == "nemoclaw-managed-inference"
if name == "OPENSHELL_TLS_KEY":
return value == "/etc/openshell/tls/client/tls.key"
if name in _MANAGED_OBSERVABILITY_ENDPOINTS:
normalized_value = value.removesuffix("/")
return normalized_value in _MANAGED_OBSERVABILITY_ENDPOINTS[name]
if name == "SLACK_BOT_TOKEN":
return bool(re.fullmatch(r"xoxb-[A-Za-z0-9_-]{10,}", value)) and not _contains_other_platform_secret(value, "slack")
if name == "SLACK_APP_TOKEN":
Expand Down
2 changes: 2 additions & 0 deletions test/langchain-deepagents-code-direct-module-patch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ check("disabled", False)
LANGCHAIN_TRACING: "true",
LANGCHAIN_TRACING_V2: "true",
OTEL_ENABLED: "true",
OTEL_EXPORTER_OTLP_ENDPOINT: "http://host.openshell.internal:4318",
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "http://host.openshell.internal:4318/v1/traces",
},
encoding: "utf8",
});
Expand Down
19 changes: 19 additions & 0 deletions test/langchain-deepagents-code-managed-entrypoints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,25 @@ describe("LangChain Deep Agents Code managed entrypoints", () => {
expect(result.stdout).toContain("analytics=1");
});

it.each([
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318"],
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/"],
["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "http://host.openshell.internal:4318/v1/traces"],
])("allows the local managed OTLP collector endpoint in %s", (name, value) => {
Comment on lines +155 to +159

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Cover the remaining allowed endpoint variants.

The implementation also accepts OTEL_EXPORTER_OTLP_ENDPOINT with /v1/traces and normalizes a trailing slash for OTEL_EXPORTER_OTLP_TRACES_ENDPOINT; add those table rows so the test proves the full public allowlist behavior. As per path instructions, “Review tests for behavioral confidence rather than implementation lock-in.”

Proposed test case additions
   it.each([
     ["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318"],
     ["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/"],
+    ["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/v1/traces"],
+    ["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/v1/traces/"],
     ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "http://host.openshell.internal:4318/v1/traces"],
+    ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "http://host.openshell.internal:4318/v1/traces/"],
   ])("allows the local managed OTLP collector endpoint in %s", (name, value) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it.each([
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318"],
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/"],
["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "http://host.openshell.internal:4318/v1/traces"],
])("allows the local managed OTLP collector endpoint in %s", (name, value) => {
it.each([
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318"],
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/"],
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/v1/traces"],
["OTEL_EXPORTER_OTLP_ENDPOINT", "http://host.openshell.internal:4318/v1/traces/"],
["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "http://host.openshell.internal:4318/v1/traces"],
["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "http://host.openshell.internal:4318/v1/traces/"],
])("allows the local managed OTLP collector endpoint in %s", (name, value) => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/langchain-deepagents-code-managed-entrypoints.test.ts` around lines 155
- 159, The table in the OTLP collector endpoint test is missing the remaining
allowed variants, so expand the `it.each` cases in
`test/langchain-deepagents-code-managed-entrypoints.test.ts` to cover
`OTEL_EXPORTER_OTLP_ENDPOINT` with `/v1/traces` and
`OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` with a trailing slash. Keep the assertion
focused on the existing allowlist behavior in the test block around the `allows
the local managed OTLP collector endpoint` case.

Source: Path instructions

const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-dcode-otel-endpoint-"));
const { wrapperPath, ranMarker } = makeWrapperFixture(tempDir);
const result = spawnSync("bash", [wrapperPath, "-n", "hi"], {
env: {
PATH: process.env.PATH ?? "/usr/bin:/bin",
[name]: value,
},
encoding: "utf8",
});

expect(result.status, result.stderr).toBe(0);
expect(fs.existsSync(ranMarker)).toBe(true);
});

it.each([
"LANGSMITH_RUNS_ENDPOINTS",
"LANGCHAIN_RUNS_ENDPOINTS",
Expand Down
Loading