Skip to content

fix: no auth and prompt protect, misc#1116

Merged
looplj merged 1 commit intorelease/v0.9.xfrom
dev-tmp
Mar 21, 2026
Merged

fix: no auth and prompt protect, misc#1116
looplj merged 1 commit intorelease/v0.9.xfrom
dev-tmp

Conversation

@looplj
Copy link
Copy Markdown
Owner

@looplj looplj commented Mar 20, 2026

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces significant improvements to the system's authentication and prompt protection capabilities. It provides a new configuration option to enable a "no-auth" API access mode, enhancing deployment flexibility. The prompt protection feature has been re-engineered for more robust and sequential application of rules, including immediate rejection for sensitive content. Additionally, comprehensive documentation for prompt protection has been added, alongside minor database configuration adjustments and general code refinements.

Highlights

  • Authentication Flexibility: Introduced a configuration option (AllowNoAuth) to enable or disable API authentication, allowing for a "no-auth" mode where a default API key is used if no key is provided.
  • Prompt Protection Enhancements: Refactored the prompt protection logic to handle multiple rules more effectively, including sequential masking and immediate rejection, and improved the return structure for rule application results.
  • Documentation: Added comprehensive documentation in both English and Chinese for the new Prompt Protection Rules feature, detailing its concepts, usage, and best practices.
  • Database Configuration: Updated the default SQLite DSN to explicitly use _pragma=journal_mode(WAL) for improved database performance and reliability.
  • API Key Handling: Improved the EnsureNoAuthAPIKey logic to check for existing no-auth keys before creation and streamlined API key authentication middleware.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request introduces a new AllowNoAuth configuration option to control API authentication behavior, updates the EnsureNoAuthAPIKey logic to check for existing keys and handle project association, and refactors the prompt protection rule application to return a more comprehensive result including all matched rules and a rejection flag. Review comments suggest improving logging for configuration values and cache errors, clarifying why the project is not cached in EnsureNoAuthAPIKey, enhancing the error message for noauth API key usage, and returning all matched prompt protection rules for better auditing.

Comment on lines +210 to 212
if apiKey.Type == apikey.TypeNoauth {
return nil, fmt.Errorf("noauth api key is only available when api auth is disabled: %w", ErrInvalidAPIKey)
}
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.

medium

This check prevents the use of noauth API keys when API authentication is enabled, which aligns with the intended security policy. However, consider adding a more descriptive error message to guide users on how to properly configure the system to use noauth keys.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 7 additional findings in Devin Review.

Open in Devin Review

Comment on lines 599 to +625
return nil, fmt.Errorf("failed to get owner user for noauth api key: %w", err)
}

scopeValues := []string{
string(scopes.ScopeReadChannels),
string(scopes.ScopeWriteRequests),
}

existing, err := client.APIKey.Query().Where(apikey.KeyEQ(NoAuthAPIKeyValue)).Only(ctx)
if err == nil {
updated, updateErr := client.APIKey.UpdateOneID(existing.ID).
SetName(NoAuthAPIKeyName).
SetType(apikey.TypeNoauth).
SetStatus(apikey.StatusEnabled).
SetScopes(scopeValues).
Save(ctx)
if updateErr != nil {
return nil, fmt.Errorf("failed to update noauth api key: %w", updateErr)
}

s.invalidateAPIKeyCaches(ctx, updated.Key)

return updated, nil
}

if !ent.IsNotFound(err) {
return nil, fmt.Errorf("failed to query noauth api key: %w", err)
}

created, err := client.APIKey.Create().
apiKey, err := client.APIKey.Create().
SetName(NoAuthAPIKeyName).
SetKey(NoAuthAPIKeyValue).
SetUserID(owner.ID).
SetProjectID(proj.ID).
SetType(apikey.TypeNoauth).
SetStatus(apikey.StatusEnabled).
SetScopes(scopeValues).
SetScopes([]string{string(scopes.ScopeWriteRequests), string(scopes.ScopeReadChannels)}).
Save(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create noauth api key: %w", err)
}

s.invalidateAPIKeyCaches(ctx, created.Key)
// DO NOT CACHE PROJECT
project, err := s.ProjectService.GetProjectByID(ctx, apiKey.ProjectID)
if err != nil {
return nil, fmt.Errorf("failed to get api key project: %w", err)
}

apiKey.Edges.Project = project

return created, nil
s.invalidateAPIKeyCaches(ctx, apiKey.Key)

return apiKey, nil
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.

🟡 Race condition in EnsureNoAuthAPIKey: concurrent first-time creation causes unique constraint violation

The old EnsureNoAuthAPIKey used an upsert pattern: query the DB directly, update if found, create if not found. The new implementation checks the cache/DB via GetAPIKey (line 580), and if the key doesn't exist (ErrInvalidAPIKey), creates it (line 602-610). However, if multiple concurrent no-auth requests arrive when the key doesn't yet exist, all will miss the cache and DB, and all will attempt Create(). Since the key field has a unique index (internal/ent/schema/api_key.go:33-35), only one will succeed — the rest will fail with a unique constraint violation, returning a 500 error to the client.

This is a regression from the old code which handled the "already exists" case gracefully via update. The new code is now called in the hot path (every request without an API key when AllowNoAuth is true via AuthenticateNoAuth at internal/server/biz/auth.go:222-224), rather than at startup, making the race window more likely to be hit on first use.

(Refers to lines 579-625)

Prompt for agents
In internal/server/biz/api_key.go, the EnsureNoAuthAPIKey function (lines 579-625) has a TOCTOU race condition. When concurrent calls both miss the cache and DB, multiple Create() calls will race and all but one will fail with a unique constraint violation on the key field.

To fix this, after the Create() call fails, catch the unique constraint violation error and retry GetAPIKey. Something like:

1. After the Create() call at line 602-610, if err is a unique constraint violation (ent.IsConstraintError(err)), retry s.GetAPIKey(ctx, NoAuthAPIKeyValue) to get the key that was created by the winning concurrent request.
2. Alternatively, re-introduce the old upsert pattern: query the DB directly with client.APIKey.Query().Where(apikey.KeyEQ(NoAuthAPIKeyValue)).Only(ctx) and update if found, create only if not found.
3. Or use a sync.Once or mutex to ensure only one goroutine creates the key.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@looplj looplj merged commit c9323d9 into release/v0.9.x Mar 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant