diff --git a/SECURITY.md b/SECURITY.md index 026e3afb70f..6104514805c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,51 +3,54 @@ # Ory Security Policy -## Overview +This policy outlines Ory's security commitments and practices for users across +different licensing and deployment models. -This security policy outlines the security support commitments for different -types of Ory users. +To learn more about Ory's security service level agreements (SLAs) and +processes, please [contact us](https://www.ory.sh/contact/). -[Get in touch](https://www.ory.sh/contact/) to learn more about Ory's security -SLAs and process. - -## Apache 2.0 License Users +## Ory Network Users -- **Security SLA:** No security Service Level Agreement (SLA) is provided. -- **Release Schedule:** Releases are planned every 3 to 6 months. These releases - will contain all security fixes implemented up to that point. -- **Version Support:** Security patches are only provided for the current - release version. +- **Security SLA:** Ory addresses vulnerabilities in the Ory Network according + to the following guidelines: + - Critical: Typically addressed within 14 days. + - High: Typically addressed within 30 days. + - Medium: Typically addressed within 90 days. + - Low: Typically addressed within 180 days. + - Informational: Addressed as necessary. + These timelines are targets and may vary based on specific circumstances. +- **Release Schedule:** Updates are deployed to the Ory Network as + vulnerabilities are resolved. +- **Version Support:** The Ory Network always runs the latest version, ensuring + up-to-date security fixes. ## Ory Enterprise License Customers -- **Security SLA:** The following timelines apply for security vulnerabilities - based on their severity: - - Critical: Resolved within 14 days. - - High: Resolved within 30 days. - - Medium: Resolved within 90 days. - - Low: Resolved within 180 days. - - Informational: Addressed as needed. -- **Release Schedule:** Updates are provided as soon as vulnerabilities are - resolved, adhering to the above SLA. -- **Version Support:** Depending on the Ory Enterprise License agreement - multiple versions can be supported. +- **Security SLA:** Ory addresses vulnerabilities based on their severity: + - Critical: Typically addressed within 14 days. + - High: Typically addressed within 30 days. + - Medium: Typically addressed within 90 days. + - Low: Typically addressed within 180 days. + - Informational: Addressed as necessary. + These timelines are targets and may vary based on specific circumstances. +- **Release Schedule:** Updates are made available as vulnerabilities are + resolved. Ory works closely with enterprise customers to ensure timely updates + that align with their operational needs. +- **Version Support:** Ory may provide security support for multiple versions, + depending on the terms of the enterprise agreement. -## Ory Network Users +## Apache 2.0 License Users -- **Security SLA:** The following timelines apply for security vulnerabilities - based on their severity: - - Critical: Resolved within 14 days. - - High: Resolved within 30 days. - - Medium: Resolved within 90 days. - - Low: Resolved within 180 days. - - Informational: Addressed as needed. -- **Release Schedule:** Updates are automatically deployed to Ory Network as - soon as vulnerabilities are resolved, adhering to the above SLA. -- **Version Support:** Ory Network always runs the most current version. +- **Security SLA:** Ory does not provide a formal SLA for security issues under + the Apache 2.0 License. +- **Release Schedule:** Releases prioritize new functionality and include fixes + for known security vulnerabilities at the time of release. While major + releases typically occur one to two times per year, Ory does not guarantee a + fixed release schedule. +- **Version Support:** Security patches are only provided for the latest release + version. ## Reporting a Vulnerability -Please head over to our -[security policy](https://www.ory.sh/docs/ecosystem/security) to learn more -about reporting security vulnerabilities. +For details on how to report security vulnerabilities, visit our +[security policy documentation](https://www.ory.sh/docs/ecosystem/security). diff --git a/persistence/sql/persister_client.go b/persistence/sql/persister_client.go index c85893c1df8..b3a484af564 100644 --- a/persistence/sql/persister_client.go +++ b/persistence/sql/persister_client.go @@ -6,6 +6,8 @@ package sql import ( "context" + "go.opentelemetry.io/otel/trace" + "github.com/ory/hydra/v2/x/events" "github.com/gobuffalo/pop/v6" @@ -20,7 +22,9 @@ import ( ) func (p *Persister) GetConcreteClient(ctx context.Context, id string) (c *client.Client, err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetConcreteClient") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetConcreteClient", + trace.WithAttributes(events.ClientID(id)), + ) defer otelx.End(span, &err) var cl client.Client @@ -35,7 +39,9 @@ func (p *Persister) GetClient(ctx context.Context, id string) (fosite.Client, er } func (p *Persister) UpdateClient(ctx context.Context, cl *client.Client) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.UpdateClient") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.UpdateClient", + trace.WithAttributes(events.ClientID(cl.ID)), + ) defer otelx.End(span, &err) return p.Transaction(ctx, func(ctx context.Context, c *pop.Connection) error { @@ -77,7 +83,9 @@ func (p *Persister) UpdateClient(ctx context.Context, cl *client.Client) (err er } func (p *Persister) AuthenticateClient(ctx context.Context, id string, secret []byte) (_ *client.Client, err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.AuthenticateClient") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.AuthenticateClient", + trace.WithAttributes(events.ClientID(id)), + ) defer otelx.End(span, &err) c, err := p.GetConcreteClient(ctx, id) @@ -117,7 +125,9 @@ func (p *Persister) CreateClient(ctx context.Context, c *client.Client) (err err } func (p *Persister) DeleteClient(ctx context.Context, id string) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteClient") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteClient", + trace.WithAttributes(events.ClientID(id)), + ) defer otelx.End(span, &err) c, err := p.GetConcreteClient(ctx, id) diff --git a/persistence/sql/persister_oauth2.go b/persistence/sql/persister_oauth2.go index 58eb107306b..7595d3b58c4 100644 --- a/persistence/sql/persister_oauth2.go +++ b/persistence/sql/persister_oauth2.go @@ -366,7 +366,9 @@ func (p *Persister) InvalidateAuthorizeCodeSession(ctx context.Context, signatur } func (p *Persister) CreateAccessTokenSession(ctx context.Context, signature string, requester fosite.Requester) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.CreateAccessTokenSession") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.CreateAccessTokenSession", + trace.WithAttributes(events.AccessTokenSignature(signature)), + ) defer otelx.End(span, &err) events.Trace(ctx, events.AccessTokenIssued, @@ -377,7 +379,9 @@ func (p *Persister) CreateAccessTokenSession(ctx context.Context, signature stri } func (p *Persister) GetAccessTokenSession(ctx context.Context, signature string, session fosite.Session) (request fosite.Requester, err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetAccessTokenSession") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetAccessTokenSession", + trace.WithAttributes(events.AccessTokenSignature(signature)), + ) defer otelx.End(span, &err) r := OAuth2RequestSQL{Table: sqlTableAccess} @@ -406,7 +410,9 @@ func (p *Persister) GetAccessTokenSession(ctx context.Context, signature string, } func (p *Persister) DeleteAccessTokenSession(ctx context.Context, signature string) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteAccessTokenSession") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteAccessTokenSession", + trace.WithAttributes(events.AccessTokenSignature(signature)), + ) defer otelx.End(span, &err) err = sqlcon.HandleError( @@ -446,7 +452,9 @@ func toEventOptions(requester fosite.Requester) []trace.EventOption { } func (p *Persister) CreateRefreshTokenSession(ctx context.Context, signature string, accessTokenSignature string, requester fosite.Requester) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.CreateRefreshTokenSession") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.CreateRefreshTokenSession", + trace.WithAttributes(events.RefreshTokenSignature(signature)), + ) defer otelx.End(span, &err) events.Trace(ctx, events.RefreshTokenIssued, toEventOptions(requester)...) @@ -476,7 +484,9 @@ func (p *Persister) CreateRefreshTokenSession(ctx context.Context, signature str } func (p *Persister) GetRefreshTokenSession(ctx context.Context, signature string, session fosite.Session) (request fosite.Requester, err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetRefreshTokenSession") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetRefreshTokenSession", + trace.WithAttributes(events.RefreshTokenSignature(signature)), + ) defer otelx.End(span, &err) var row OAuth2RefreshTable @@ -506,7 +516,9 @@ func (p *Persister) GetRefreshTokenSession(ctx context.Context, signature string } func (p *Persister) DeleteRefreshTokenSession(ctx context.Context, signature string) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteRefreshTokenSession") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteRefreshTokenSession", + trace.WithAttributes(events.RefreshTokenSignature(signature)), + ) defer otelx.End(span, &err) return p.deleteSessionBySignature(ctx, signature, sqlTableRefresh) } @@ -551,13 +563,17 @@ func (p *Persister) DeletePKCERequestSession(ctx context.Context, signature stri } func (p *Persister) RevokeRefreshToken(ctx context.Context, id string) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.RevokeRefreshToken") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.RevokeRefreshToken", + trace.WithAttributes(events.ConsentRequestID(id)), + ) defer otelx.End(span, &err) return p.deleteSessionByRequestID(ctx, id, sqlTableRefresh) } func (p *Persister) RevokeAccessToken(ctx context.Context, id string) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.RevokeAccessToken") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.RevokeAccessToken", + trace.WithAttributes(events.ConsentRequestID(id)), + ) defer otelx.End(span, &err) return p.deleteSessionByRequestID(ctx, id, sqlTableAccess) } @@ -609,7 +625,9 @@ func (p *Persister) FlushInactiveRefreshTokens(ctx context.Context, notAfter tim } func (p *Persister) DeleteAccessTokens(ctx context.Context, clientID string) (err error) { - ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteAccessTokens") + ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.DeleteAccessTokens", + trace.WithAttributes(events.ClientID(clientID)), + ) defer otelx.End(span, &err) /* #nosec G201 table is static */ return sqlcon.HandleError( diff --git a/test/e2e/oauth2-client/package-lock.json b/test/e2e/oauth2-client/package-lock.json index 33091833146..ffbd7675356 100644 --- a/test/e2e/oauth2-client/package-lock.json +++ b/test/e2e/oauth2-client/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "body-parser": "^1.20.1", "dotenv": "^7.0.0", - "express": "^4.21.0", + "express": "^4.21.2", "express-session": "^1.17.0", "express-winston": "^3.4.0", "hydra-login-consent-logout": "2.0.4-pre.2", @@ -1074,16 +1074,16 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -1097,7 +1097,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -1112,6 +1112,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express-session": { @@ -1161,9 +1165,9 @@ } }, "node_modules/express/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -2528,9 +2532,9 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -4340,16 +4344,16 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -4363,7 +4367,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -4378,9 +4382,9 @@ }, "dependencies": { "cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" }, "depd": { "version": "2.0.0", @@ -5463,9 +5467,9 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, "path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "picomatch": { "version": "2.3.1", diff --git a/test/e2e/oauth2-client/package.json b/test/e2e/oauth2-client/package.json index 5bd2a74b983..90412a46396 100644 --- a/test/e2e/oauth2-client/package.json +++ b/test/e2e/oauth2-client/package.json @@ -11,7 +11,7 @@ "dependencies": { "body-parser": "^1.20.1", "dotenv": "^7.0.0", - "express": "^4.21.0", + "express": "^4.21.2", "express-session": "^1.17.0", "express-winston": "^3.4.0", "hydra-login-consent-logout": "2.0.4-pre.2", diff --git a/x/events/events.go b/x/events/events.go index b93843f9db9..998892f77d9 100644 --- a/x/events/events.go +++ b/x/events/events.go @@ -58,11 +58,14 @@ const ( ) const ( - attributeKeyOAuth2ClientName = "OAuth2ClientName" - attributeKeyOAuth2ClientID = "OAuth2ClientID" - attributeKeyOAuth2Subject = "OAuth2Subject" - attributeKeyOAuth2GrantType = "OAuth2GrantType" - attributeKeyOAuth2TokenFormat = "OAuth2TokenFormat" //nolint:gosec + attributeKeyOAuth2ClientName = "OAuth2ClientName" + attributeKeyOAuth2ClientID = "OAuth2ClientID" + attributeKeyOAuth2Subject = "OAuth2Subject" + attributeKeyOAuth2GrantType = "OAuth2GrantType" + attributeKeyOAuth2ConsentRequestID = "OAuth2ConsentRequestID" + attributeKeyOAuth2TokenFormat = "OAuth2TokenFormat" //nolint:gosec + attributeKeyOAuth2RefreshTokenSignature = "OAuth2RefreshTokenSignature" //nolint:gosec + attributeKeyOAuth2AccessTokenSignature = "OAuth2AccessTokenSignature" //nolint:gosec ) // WithTokenFormat emits the token format as part of the event. @@ -75,9 +78,25 @@ func WithGrantType(grantType string) trace.EventOption { return trace.WithAttributes(otelattr.String(attributeKeyOAuth2GrantType, grantType)) } +func ClientID(clientID string) otelattr.KeyValue { + return otelattr.String(attributeKeyOAuth2ClientID, clientID) +} + +func RefreshTokenSignature(signature string) otelattr.KeyValue { + return otelattr.String(attributeKeyOAuth2RefreshTokenSignature, signature) +} + +func AccessTokenSignature(signature string) otelattr.KeyValue { + return otelattr.String(attributeKeyOAuth2AccessTokenSignature, signature) +} + +func ConsentRequestID(id string) otelattr.KeyValue { + return otelattr.String(attributeKeyOAuth2ConsentRequestID, id) +} + // WithClientID emits the client ID as part of the event. func WithClientID(clientID string) trace.EventOption { - return trace.WithAttributes(otelattr.String(attributeKeyOAuth2ClientID, clientID)) + return trace.WithAttributes(ClientID(clientID)) } // WithClientName emits the client name as part of the event.