diff --git a/changelogs/unreleased/fix-guest-access-posting-to-notes.yml b/changelogs/unreleased/fix-guest-access-posting-to-notes.yml
new file mode 100644
index 0000000000000000000000000000000000000000..81377c0c6f0814d10a2f2c1f886d3bfdf9a5afdb
--- /dev/null
+++ b/changelogs/unreleased/fix-guest-access-posting-to-notes.yml
@@ -0,0 +1,4 @@
+---
+title: Prevent users from creating notes on resources they can't access
+merge_request:
+author:
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 284e4cf549ad9fb7920046c7dee90eaced1116fa..4d2a8f482670c35bd5ea1a5208de01918af8a8da 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -70,21 +70,27 @@ module API
         end
         post ":id/#{noteables_str}/:noteable_id/notes" do
           opts = {
-           note: params[:body],
-           noteable_type: noteables_str.classify,
-           noteable_id: params[:noteable_id]
+            note: params[:body],
+            noteable_type: noteables_str.classify,
+            noteable_id: params[:noteable_id]
           }
 
-          if params[:created_at] && (current_user.is_admin? || user_project.owner == current_user)
-            opts[:created_at] = params[:created_at]
-          end
+          noteable = user_project.send(noteables_str.to_sym).find(params[:noteable_id])
+
+          if can?(current_user, noteable_read_ability_name(noteable), noteable)
+            if params[:created_at] && (current_user.is_admin? || user_project.owner == current_user)
+              opts[:created_at] = params[:created_at]
+            end
 
-          note = ::Notes::CreateService.new(user_project, current_user, opts).execute
+            note = ::Notes::CreateService.new(user_project, current_user, opts).execute
 
-          if note.valid?
-            present note, with: Entities::const_get(note.class.name)
+            if note.valid?
+              present note, with: Entities::const_get(note.class.name)
+            else
+              not_found!("Note #{note.errors.messages}")
+            end
           else
-            not_found!("Note #{note.errors.messages}")
+            not_found!("Note")
           end
         end
 
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 0f8d054b31e97787d8ad59bbdacdbb9c0b314b04..0353ebea9e59b3c518ea17bcf01a98e24c0f3aa1 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -264,6 +264,18 @@ describe API::Notes, api: true  do
       end
     end
 
+    context 'when user does not have access to read the noteable' do
+      it 'responds with 404' do
+        project = create(:empty_project, :private) { |p| p.add_guest(user) }
+        issue = create(:issue, :confidential, project: project)
+
+        post api("/projects/#{project.id}/issues/#{issue.id}/notes", user),
+          body: 'Foo'
+
+        expect(response).to have_http_status(404)
+      end
+    end
+
     context 'when user does not have access to create noteable' do
       let(:private_issue) { create(:issue, project: create(:empty_project, :private)) }