diff --git a/src/components/ui/__tests__/password-input.test.tsx b/src/components/ui/__tests__/password-input.test.tsx
new file mode 100644
index 000000000..dadb1389d
--- /dev/null
+++ b/src/components/ui/__tests__/password-input.test.tsx
@@ -0,0 +1,44 @@
+import { describe, it, expect } from "vitest";
+import { renderToStaticMarkup } from "react-dom/server";
+
+import { I18nProvider } from "@/lib/i18n/context";
+import { PasswordInput } from "../password-input";
+
+/**
+ * PasswordInput bakes the password-manager autofill guard in by default so
+ * BYOK API keys / webhook secrets / ntfy tokens (config secrets, not
+ * credentials) are never offered up to Bitwarden / 1Password / LastPass.
+ * Credential fields that pass a real autocomplete token keep manager
+ * integration.
+ */
+function render(node: React.ReactNode) {
+ return renderToStaticMarkup(
+ {node},
+ );
+}
+
+describe("PasswordInput", () => {
+ it("suppresses password managers by default for config secrets", () => {
+ const html = render();
+ expect(html).toMatch(/autocomplete="off"/i);
+ expect(html).toContain("data-bwignore");
+ expect(html).toContain("data-1p-ignore");
+ expect(html).toContain('data-lpignore="true"');
+ });
+
+ it("treats an explicit autoComplete=off as a config secret too", () => {
+ const html = render();
+ expect(html).toContain("data-bwignore");
+ expect(html).toContain("data-1p-ignore");
+ });
+
+ it("keeps manager integration for credential fields", () => {
+ const html = render(
+ ,
+ );
+ expect(html).toMatch(/autocomplete="current-password"/i);
+ expect(html).not.toContain("data-bwignore");
+ expect(html).not.toContain("data-1p-ignore");
+ expect(html).not.toContain("data-lpignore");
+ });
+});
diff --git a/src/components/ui/password-input.tsx b/src/components/ui/password-input.tsx
index 7e1ac7625..e9149c3ce 100644
--- a/src/components/ui/password-input.tsx
+++ b/src/components/ui/password-input.tsx
@@ -22,14 +22,28 @@ import { useTranslations } from "@/lib/i18n/context";
*/
export function PasswordInput({
className,
+ autoComplete,
...props
}: React.ComponentProps) {
const [visible, setVisible] = useState(false);
const { t } = useTranslations();
+
+ // Config/secret fields (BYOK API keys, webhook secrets, ntfy tokens) pass no
+ // `autoComplete` — they are not credentials, so a password manager offering
+ // to fill or *save* them is noise and risks clobbering the field. Suppress
+ // Bitwarden / 1Password / LastPass by default for those. Credential fields
+ // (login, register, password change) pass a real token
+ // (`current-password` / `new-password` / `username`) and keep manager
+ // integration; only an explicit `"off"` opts back into suppression.
+ const suppressManagers = autoComplete == null || autoComplete === "off";
return (