Skip to content

Commit 815baf9

Browse files
committed
Return vague 404
1 parent a6d15ed commit 815baf9

20 files changed

+79
-77
lines changed

coderd/files.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func (api *API) fileByHash(rw http.ResponseWriter, r *http.Request) {
8787
}
8888
file, err := api.Database.GetFileByHash(r.Context(), hash)
8989
if errors.Is(err, sql.ErrNoRows) {
90-
httpapi.ResourceNotFound(rw, fmt.Sprintf("File %q", hash))
90+
httpapi.ResourceNotFound(rw)
9191
return
9292
}
9393
if err != nil {
@@ -101,7 +101,7 @@ func (api *API) fileByHash(rw http.ResponseWriter, r *http.Request) {
101101
if !api.Authorize(r, rbac.ActionRead,
102102
rbac.ResourceFile.WithOwner(file.CreatedBy.String()).WithID(file.Hash)) {
103103
// Return 404 to not leak the file exists
104-
httpapi.ResourceNotFound(rw, fmt.Sprintf("File %q", hash))
104+
httpapi.ResourceNotFound(rw)
105105
return
106106
}
107107

coderd/gitsshkey.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
1515
user := httpmw.UserParam(r)
1616

1717
if !api.Authorize(r, rbac.ActionUpdate, rbac.ResourceUserData.WithOwner(user.ID.String())) {
18-
httpapi.Forbidden(rw)
18+
httpapi.ResourceNotFound(rw)
1919
return
2020
}
2121

@@ -64,7 +64,7 @@ func (api *API) gitSSHKey(rw http.ResponseWriter, r *http.Request) {
6464
user := httpmw.UserParam(r)
6565

6666
if !api.Authorize(r, rbac.ActionRead, rbac.ResourceUserData.WithOwner(user.ID.String())) {
67-
httpapi.Forbidden(rw)
67+
httpapi.ResourceNotFound(rw)
6868
return
6969
}
7070

coderd/httpapi/httpapi.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ type Error struct {
7676
Detail string `json:"detail" validate:"required"`
7777
}
7878

79-
func ResourceNotFound(rw http.ResponseWriter, resource string) {
79+
// ResourceNotFound is intentionally vague. All 404 responses should be identical
80+
// to prevent leaking existence of resources.
81+
func ResourceNotFound(rw http.ResponseWriter) {
8082
Write(rw, http.StatusNotFound, Response{
81-
Message: fmt.Sprintf("%s does not exist.", resource),
83+
Message: fmt.Sprintf("Resource not found"),
8284
})
8385
}
8486

coderd/httpmw/organizationparam.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"database/sql"
66
"errors"
7-
"fmt"
87
"net/http"
98

109
"github.com/coder/coder/coderd/database"
@@ -45,7 +44,7 @@ func ExtractOrganizationParam(db database.Store) func(http.Handler) http.Handler
4544

4645
organization, err := db.GetOrganizationByID(r.Context(), orgID)
4746
if errors.Is(err, sql.ErrNoRows) {
48-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Organization %q", orgID))
47+
httpapi.ResourceNotFound(rw)
4948
return
5049
}
5150
if err != nil {

coderd/httpmw/templateparam.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func ExtractTemplateParam(db database.Store) func(http.Handler) http.Handler {
4747
}
4848

4949
if template.Deleted {
50-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q", templateID))
50+
httpapi.ResourceNotFound(rw)
5151
return
5252
}
5353

coderd/httpmw/templateversionparam.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"database/sql"
66
"errors"
7-
"fmt"
87
"net/http"
98

109
"github.com/go-chi/chi/v5"
@@ -34,7 +33,7 @@ func ExtractTemplateVersionParam(db database.Store) func(http.Handler) http.Hand
3433
}
3534
templateVersion, err := db.GetTemplateVersionByID(r.Context(), templateVersionID)
3635
if errors.Is(err, sql.ErrNoRows) {
37-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersionID))
36+
httpapi.ResourceNotFound(rw)
3837
return
3938
}
4039
if err != nil {

coderd/httpmw/userparam.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package httpmw
22

33
import (
44
"context"
5+
"database/sql"
56
"net/http"
67

8+
"golang.org/x/xerrors"
9+
710
"github.com/go-chi/chi/v5"
811
"github.com/google/uuid"
912

@@ -47,6 +50,10 @@ func ExtractUserParam(db database.Store) func(http.Handler) http.Handler {
4750

4851
if userQuery == "me" {
4952
user, err = db.GetUserByID(r.Context(), APIKey(r).UserID)
53+
if xerrors.Is(err, sql.ErrNoRows) {
54+
httpapi.ResourceNotFound(rw)
55+
return
56+
}
5057
if err != nil {
5158
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
5259
Message: "Internal error fetching user.",

coderd/httpmw/workspacebuildparam.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"database/sql"
66
"errors"
7-
"fmt"
87
"net/http"
98

109
"github.com/go-chi/chi/v5"
@@ -34,7 +33,7 @@ func ExtractWorkspaceBuildParam(db database.Store) func(http.Handler) http.Handl
3433
}
3534
workspaceBuild, err := db.GetWorkspaceBuildByID(r.Context(), workspaceBuildID)
3635
if errors.Is(err, sql.ErrNoRows) {
37-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Workspace build %q", workspaceBuildID))
36+
httpapi.ResourceNotFound(rw)
3837
return
3938
}
4039
if err != nil {

coderd/httpmw/workspaceparam.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"database/sql"
66
"errors"
7-
"fmt"
87
"net/http"
98

109
"github.com/coder/coder/coderd/database"
@@ -32,7 +31,7 @@ func ExtractWorkspaceParam(db database.Store) func(http.Handler) http.Handler {
3231
}
3332
workspace, err := db.GetWorkspaceByID(r.Context(), workspaceID)
3433
if errors.Is(err, sql.ErrNoRows) {
35-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Workspace %q", workspaceID))
34+
httpapi.ResourceNotFound(rw)
3635
return
3736
}
3837
if err != nil {

coderd/organizations.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (api *API) organization(rw http.ResponseWriter, r *http.Request) {
2222
if !api.Authorize(r, rbac.ActionRead, rbac.ResourceOrganization.
2323
InOrg(organization.ID).
2424
WithID(organization.ID.String())) {
25-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Organization %q", organization.ID))
25+
httpapi.ResourceNotFound(rw)
2626
return
2727
}
2828

@@ -33,8 +33,7 @@ func (api *API) postOrganizations(rw http.ResponseWriter, r *http.Request) {
3333
apiKey := httpmw.APIKey(r)
3434
// Create organization uses the organization resource without an OrgID.
3535
// This means you need the site wide permission to make a new organization.
36-
if !api.Authorize(r, rbac.ActionCreate,
37-
rbac.ResourceOrganization) {
36+
if !api.Authorize(r, rbac.ActionCreate, rbac.ResourceOrganization) {
3837
httpapi.Forbidden(rw)
3938
return
4039
}

coderd/parameters.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (api *API) postParameter(rw http.ResponseWriter, r *http.Request) {
2727
return
2828
}
2929
if !api.Authorize(r, rbac.ActionUpdate, obj) {
30-
httpapi.Forbidden(rw)
30+
httpapi.ResourceNotFound(rw)
3131
return
3232
}
3333

@@ -87,7 +87,7 @@ func (api *API) parameters(rw http.ResponseWriter, r *http.Request) {
8787
}
8888

8989
if !api.Authorize(r, rbac.ActionRead, obj) {
90-
httpapi.Forbidden(rw)
90+
httpapi.ResourceNotFound(rw)
9191
return
9292
}
9393

@@ -124,7 +124,7 @@ func (api *API) deleteParameter(rw http.ResponseWriter, r *http.Request) {
124124
}
125125
// A deleted param is still updating the underlying resource for the scope.
126126
if !api.Authorize(r, rbac.ActionUpdate, obj) {
127-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Parameter %q with scope %q", scopeID, scope))
127+
httpapi.ResourceNotFound(rw)
128128
return
129129
}
130130

@@ -135,7 +135,7 @@ func (api *API) deleteParameter(rw http.ResponseWriter, r *http.Request) {
135135
Name: name,
136136
})
137137
if errors.Is(err, sql.ErrNoRows) {
138-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Parameter %q with scope %q", scopeID, scope))
138+
httpapi.ResourceNotFound(rw)
139139
return
140140
}
141141
if err != nil {

coderd/roles.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (api *API) checkPermissions(rw http.ResponseWriter, r *http.Request) {
4444
user := httpmw.UserParam(r)
4545

4646
if !api.Authorize(r, rbac.ActionRead, rbac.ResourceUser.WithID(user.ID.String())) {
47-
httpapi.Forbidden(rw)
47+
httpapi.ResourceNotFound(rw)
4848
return
4949
}
5050

coderd/templates.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func (api *API) template(rw http.ResponseWriter, r *http.Request) {
2929
template := httpmw.TemplateParam(r)
3030

3131
if !api.Authorize(r, rbac.ActionRead, template) {
32-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q", template.ID))
32+
httpapi.ResourceNotFound(rw)
3333
return
3434
}
3535

@@ -56,7 +56,7 @@ func (api *API) template(rw http.ResponseWriter, r *http.Request) {
5656
func (api *API) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
5757
template := httpmw.TemplateParam(r)
5858
if !api.Authorize(r, rbac.ActionDelete, template) {
59-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q", template.ID))
59+
httpapi.ResourceNotFound(rw)
6060
return
6161
}
6262

@@ -100,7 +100,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
100100
var createTemplate codersdk.CreateTemplateRequest
101101
organization := httpmw.OrganizationParam(r)
102102
if !api.Authorize(r, rbac.ActionCreate, rbac.ResourceTemplate.InOrg(organization.ID)) {
103-
httpapi.Forbidden(rw)
103+
httpapi.ResourceNotFound(rw)
104104
return
105105
}
106106

@@ -273,7 +273,7 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
273273
})
274274
if err != nil {
275275
if errors.Is(err, sql.ErrNoRows) {
276-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q in organization %q", templateName, organization.Name))
276+
httpapi.ResourceNotFound(rw)
277277
return
278278
}
279279

@@ -285,7 +285,7 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
285285
}
286286

287287
if !api.Authorize(r, rbac.ActionRead, template) {
288-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q in organization %q", templateName, organization.Name))
288+
httpapi.ResourceNotFound(rw)
289289
return
290290
}
291291

@@ -312,7 +312,7 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
312312
func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
313313
template := httpmw.TemplateParam(r)
314314
if !api.Authorize(r, rbac.ActionUpdate, template) {
315-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q", template.ID))
315+
httpapi.ResourceNotFound(rw)
316316
return
317317
}
318318

coderd/templateversions.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) {
2424
templateVersion := httpmw.TemplateVersionParam(r)
2525
if !api.Authorize(r, rbac.ActionRead, templateVersion) {
26-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
26+
httpapi.ResourceNotFound(rw)
2727
return
2828
}
2929

@@ -42,7 +42,7 @@ func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) {
4242
func (api *API) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Request) {
4343
templateVersion := httpmw.TemplateVersionParam(r)
4444
if !api.Authorize(r, rbac.ActionUpdate, templateVersion) {
45-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
45+
httpapi.ResourceNotFound(rw)
4646
return
4747
}
4848

@@ -88,7 +88,7 @@ func (api *API) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Reque
8888
func (api *API) templateVersionSchema(rw http.ResponseWriter, r *http.Request) {
8989
templateVersion := httpmw.TemplateVersionParam(r)
9090
if !api.Authorize(r, rbac.ActionRead, templateVersion) {
91-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
91+
httpapi.ResourceNotFound(rw)
9292
return
9393
}
9494

@@ -136,7 +136,7 @@ func (api *API) templateVersionParameters(rw http.ResponseWriter, r *http.Reques
136136
apiKey := httpmw.APIKey(r)
137137
templateVersion := httpmw.TemplateVersionParam(r)
138138
if !api.Authorize(r, rbac.ActionRead, templateVersion) {
139-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
139+
httpapi.ResourceNotFound(rw)
140140
return
141141
}
142142

@@ -180,14 +180,14 @@ func (api *API) postTemplateVersionDryRun(rw http.ResponseWriter, r *http.Reques
180180
apiKey := httpmw.APIKey(r)
181181
templateVersion := httpmw.TemplateVersionParam(r)
182182
if !api.Authorize(r, rbac.ActionRead, templateVersion) {
183-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
183+
httpapi.ResourceNotFound(rw)
184184
return
185185
}
186186
// We use the workspace RBAC check since we don't want to allow dry runs if
187187
// the user can't create workspaces.
188188
if !api.Authorize(r, rbac.ActionCreate,
189189
rbac.ResourceWorkspace.InOrg(templateVersion.OrganizationID).WithOwner(apiKey.UserID.String())) {
190-
httpapi.Forbidden(rw)
190+
httpapi.ResourceNotFound(rw)
191191
return
192192
}
193193

@@ -301,7 +301,7 @@ func (api *API) patchTemplateVersionDryRunCancel(rw http.ResponseWriter, r *http
301301
}
302302
if !api.Authorize(r, rbac.ActionUpdate,
303303
rbac.ResourceWorkspace.InOrg(templateVersion.OrganizationID).WithOwner(job.InitiatorID.String())) {
304-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
304+
httpapi.ResourceNotFound(rw)
305305
return
306306
}
307307

@@ -344,7 +344,7 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re
344344
jobID = chi.URLParam(r, "jobID")
345345
)
346346
if !api.Authorize(r, rbac.ActionRead, templateVersion) {
347-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
347+
httpapi.ResourceNotFound(rw)
348348
return database.ProvisionerJob{}, false
349349
}
350350

@@ -403,7 +403,7 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re
403403
func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Request) {
404404
template := httpmw.TemplateParam(r)
405405
if !api.Authorize(r, rbac.ActionRead, template) {
406-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q", template.ID))
406+
httpapi.ResourceNotFound(rw)
407407
return
408408
}
409409

@@ -491,7 +491,7 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque
491491
func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
492492
template := httpmw.TemplateParam(r)
493493
if !api.Authorize(r, rbac.ActionRead, template) {
494-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q", template.ID))
494+
httpapi.ResourceNotFound(rw)
495495
return
496496
}
497497

@@ -531,7 +531,7 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
531531
func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Request) {
532532
template := httpmw.TemplateParam(r)
533533
if !api.Authorize(r, rbac.ActionUpdate, template) {
534-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template %q", template.ID))
534+
httpapi.ResourceNotFound(rw)
535535
return
536536
}
537537

@@ -618,12 +618,12 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
618618

619619
// Making a new template version is the same permission as creating a new template.
620620
if !api.Authorize(r, rbac.ActionCreate, rbac.ResourceTemplate.InOrg(organization.ID)) {
621-
httpapi.Forbidden(rw)
621+
httpapi.ResourceNotFound(rw)
622622
return
623623
}
624624

625625
if !api.Authorize(r, rbac.ActionRead, file) {
626-
httpapi.Forbidden(rw)
626+
httpapi.ResourceNotFound(rw)
627627
return
628628
}
629629

@@ -705,7 +705,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
705705
func (api *API) templateVersionResources(rw http.ResponseWriter, r *http.Request) {
706706
templateVersion := httpmw.TemplateVersionParam(r)
707707
if !api.Authorize(r, rbac.ActionRead, templateVersion) {
708-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
708+
httpapi.ResourceNotFound(rw)
709709
return
710710
}
711711

@@ -727,7 +727,7 @@ func (api *API) templateVersionResources(rw http.ResponseWriter, r *http.Request
727727
func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) {
728728
templateVersion := httpmw.TemplateVersionParam(r)
729729
if !api.Authorize(r, rbac.ActionRead, templateVersion) {
730-
httpapi.ResourceNotFound(rw, fmt.Sprintf("Template version %q", templateVersion.ID))
730+
httpapi.ResourceNotFound(rw)
731731
return
732732
}
733733

0 commit comments

Comments
 (0)